QA restore security, COAR sub section fix emptying request services, restore "openaire" lowercase as a Source.

This commit is contained in:
frabacche
2024-02-29 10:11:03 +01:00
parent 37e38c9ad9
commit 9b795b7dbd
20 changed files with 202 additions and 275 deletions

View File

@@ -13,8 +13,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.Date; import java.util.Date;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.dspace.qaevent.service.dto.NotifyMessageDTO;
import org.dspace.qaevent.service.dto.CorrectionTypeMessageDTO; import org.dspace.qaevent.service.dto.CorrectionTypeMessageDTO;
import org.dspace.qaevent.service.dto.NotifyMessageDTO;
import org.dspace.qaevent.service.dto.OpenaireMessageDTO; import org.dspace.qaevent.service.dto.OpenaireMessageDTO;
import org.dspace.qaevent.service.dto.QAMessageDTO; import org.dspace.qaevent.service.dto.QAMessageDTO;
import org.dspace.util.RawJsonDeserializer; import org.dspace.util.RawJsonDeserializer;
@@ -32,7 +32,7 @@ public class QAEvent {
public static final String REJECTED = "rejected"; public static final String REJECTED = "rejected";
public static final String DISCARDED = "discarded"; public static final String DISCARDED = "discarded";
public static final String OPENAIRE_SOURCE = "OpenAIRE"; public static final String OPENAIRE_SOURCE = "openaire";
public static final String DSPACE_USERS_SOURCE = "DSpaceUsers"; public static final String DSPACE_USERS_SOURCE = "DSpaceUsers";
public static final String COAR_NOTIFY_SOURCE = "coar-notify"; public static final String COAR_NOTIFY_SOURCE = "coar-notify";
@@ -205,18 +205,16 @@ public class QAEvent {
} }
public Class<? extends QAMessageDTO> getMessageDtoClass() { public Class<? extends QAMessageDTO> getMessageDtoClass() {
Class<? extends QAMessageDTO> result = null;
switch (getSource()) { switch (getSource()) {
case OPENAIRE_SOURCE: case OPENAIRE_SOURCE:
result = OpenaireMessageDTO.class; return OpenaireMessageDTO.class;
break;
case COAR_NOTIFY_SOURCE: case COAR_NOTIFY_SOURCE:
result = NotifyMessageDTO.class; return NotifyMessageDTO.class;
break; case DSPACE_USERS_SOURCE:
return CorrectionTypeMessageDTO.class;
default: default:
throw new IllegalArgumentException("Unknown event's source: " + getSource()); throw new IllegalArgumentException("Unknown event's source: " + getSource());
} }
return result;
} }
} }

View File

@@ -21,6 +21,7 @@ public class QANotifyPatterns {
public static final String TOPIC_ENRICH_MORE_ENDORSEMENT = "ENRICH/MORE/ENDORSEMENT"; public static final String TOPIC_ENRICH_MORE_ENDORSEMENT = "ENRICH/MORE/ENDORSEMENT";
public static final String TOPIC_ENRICH_MORE_PID = "ENRICH/MORE/PID"; public static final String TOPIC_ENRICH_MORE_PID = "ENRICH/MORE/PID";
public static final String TOPIC_ENRICH_MISSING_PID = "ENRICH/MISSING/PID"; public static final String TOPIC_ENRICH_MISSING_PID = "ENRICH/MISSING/PID";
public static final String TOPIC_ENRICH_MORE_LINK = "ENRICH/MORE/LINK";
/** /**
* Default constructor * Default constructor

View File

@@ -38,7 +38,7 @@ public interface QAEventService {
/** /**
* Find all the event's topics related to the given source. * Find all the event's topics related to the given source.
* *
* @param context the DSpace context * @param context the DSpace context
* @param source the source to search for * @param source the source to search for
* @param offset the offset to apply * @param offset the offset to apply
* @param count the page size * @param count the page size
@@ -47,7 +47,7 @@ public interface QAEventService {
* @return the topics list * @return the topics list
*/ */
public List<QATopic> findAllTopicsBySource(Context context, String source, long offset, long count, public List<QATopic> findAllTopicsBySource(Context context, String source, long offset, long count,
String orderField, boolean ascending); String orderField, boolean ascending);
/** /**
* Find a specific topic by its name, source and optionally a target. * Find a specific topic by its name, source and optionally a target.
@@ -60,6 +60,13 @@ public interface QAEventService {
*/ */
public QATopic findTopicBySourceAndNameAndTarget(Context context, String sourceName, String topicName, UUID target); public QATopic findTopicBySourceAndNameAndTarget(Context context, String sourceName, String topicName, UUID target);
/**
* Count all the event's topics.
*
* @return the count result
*/
public long countTopics();
/** /**
* Count all the event's topics related to the given source. * Count all the event's topics related to the given source.
* *
@@ -70,13 +77,15 @@ public interface QAEventService {
public long countTopicsBySource(Context context, String source); public long countTopicsBySource(Context context, String source);
/** /**
* Find all the events by topic sorted by trust descending. * Find all the events by topic.
* *
* @param context the DSpace context * @param context the DSpace context
* @param sourceName the source name * @param sourceName the source name
* @param topic the topic to search for * @param topic the topic to search for
* @param offset the offset to apply * @param offset the offset to apply
* @param size the page size * @param size the page size
* @param orderField the field to order for
* @param ascending true if the order should be ascending, false otherwise
* @return the events * @return the events
*/ */
public List<QAEvent> findEventsByTopic(Context context, String sourceName, String topic, long offset, int size, public List<QAEvent> findEventsByTopic(Context context, String sourceName, String topic, long offset, int size,
@@ -93,12 +102,12 @@ public interface QAEventService {
public long countEventsByTopic(Context context, String sourceName, String topic); public long countEventsByTopic(Context context, String sourceName, String topic);
/** /**
* Find an event by the given id. * Find an event by the given id. Please note that no security filter are applied by this method.
* @param id the id of the event to search for
* *
* @param id the id of the event to search for
* @return the event * @return the event
*/ */
public QAEvent findEventByEventId(Context context, String id); public QAEvent findEventByEventId(String id);
/** /**
* Store the given event. * Store the given event.
@@ -122,6 +131,14 @@ public interface QAEventService {
*/ */
public void deleteEventsByTargetId(UUID targetId); public void deleteEventsByTargetId(UUID targetId);
/**
* Find a specific topid by the given id.
*
* @param topicId the topic id to search for
* @return the topic
*/
public QATopic findTopicByTopicId(String topicId);
/** /**
* Find a specific source by the given name. * Find a specific source by the given name.
* *
@@ -137,7 +154,7 @@ public interface QAEventService {
* @param context the DSpace context * @param context the DSpace context
* @param source the source name * @param source the source name
* @param target the uuid of the item target * @param target the uuid of the item target
* @return the source * @return the source
*/ */
public QASource findSource(Context context, String source, UUID target); public QASource findSource(Context context, String source, UUID target);
@@ -174,7 +191,7 @@ public interface QAEventService {
* @param context the DSpace context * @param context the DSpace context
* @param target the item uuid * @param target the item uuid
* @param source the source to search for * @param source the source to search for
* @return countTopicsBySourceAndTarget the count result * @return the count result
*/ */
public long countTopicsBySourceAndTarget(Context context, String source, UUID target); public long countTopicsBySourceAndTarget(Context context, String source, UUID target);
@@ -190,53 +207,16 @@ public interface QAEventService {
* Find a list of QA events according to the pagination parameters for the specified topic and target sorted by * Find a list of QA events according to the pagination parameters for the specified topic and target sorted by
* trust descending * trust descending
* *
* @param context the DSpace context * @param context the DSpace context
* @param source the source name * @param source the source name
* @param topic the topic to search for * @param topic the topic to search for
* @param offset the offset to apply * @param offset the offset to apply
* @param pageSize the page size * @param pageSize the page size
* @param target the uuid of the QA event's target * @param target the uuid of the QA event's target
* @return the events * @return the events
*/ */
public List<QAEvent> findEventsByTopicAndPageAndTarget(Context context, String source, String topic, long offset, public List<QAEvent> findEventsByTopicAndTarget(Context context, String source, String topic, UUID target,
int pageSize, UUID target); long offset, int pageSize);
/**
* Count the QA events related to the specified topic and target
*
* @param context the DSpace context
* @param source the source name
* @param topic the topic to search for
* @param target the uuid of the QA event's target
* @return the count result
*/
public long countEventsByTopicAndTarget(Context context, String source, String topic, UUID target);
/**
* Find all the event's topics related to the given source for a specific item
*
* @param context the DSpace context
* @param source (not null) the source to search for
* @param target the item referring to
* @param offset the offset to apply
* @param count result count
* @param orderField field name for sorting
* @param ascending activate ascending sort
* @return the topics list
*/
public List<QATopic> findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset,
long count, String orderField, boolean ascending);
/**
* Find all the event's sources related to a specific item
*
* @param context the DSpace context
* @param target the item referring to
* @param offset the offset to apply
* @param pageSize the page size
* @return the source list
*/
public List<QASource> findAllSourcesByTarget(Context context, UUID target, long offset, int pageSize);
/** /**
* Check if a qaevent with the provided id is visible to the current user according to the source security * Check if a qaevent with the provided id is visible to the current user according to the source security
@@ -249,4 +229,39 @@ public interface QAEventService {
*/ */
public boolean qaEventsInSource(Context context, EPerson user, String eventId, String source); public boolean qaEventsInSource(Context context, EPerson user, String eventId, String source);
/**
* Count the QA events related to the specified topic and target
*
* @param context the DSpace context
* @param source the source name
* @param topic the topic to search for
* @param target the uuid of the QA event's target
* @return the count result
*/
public long countEventsByTopicAndTarget(Context context, String source, String topic, UUID target);
/**
* Find all the event's sources related to a specific item
*
* @param context the DSpace context
* @param target the item referring to
* @param offset the offset to apply
* @param pageSize the page size
* @return the source list
*/
public List<QASource> findAllSourcesByTarget(Context context, UUID target, long offset, int pageSize);
/**
* Find all the event's topics related to the given source for a specific item
*
* @param context the DSpace context
* @param source (not null) the source to search for
* @param target the item referring to
* @param offset the offset to apply
* @param pageSize the page size
* @return the topics list
*/
public List<QATopic> findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset,
long pageSize, String orderField, boolean ascending);
} }

View File

@@ -16,6 +16,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
@@ -28,6 +29,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.json.JsonMapper;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
@@ -42,13 +44,14 @@ import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.FacetParams; import org.apache.solr.common.params.FacetParams;
import org.dspace.content.Item;
import org.dspace.content.QAEvent; import org.dspace.content.QAEvent;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.core.Email; import org.dspace.core.Email;
import org.dspace.core.I18nUtil; import org.dspace.core.I18nUtil;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.handle.service.HandleService;
import org.dspace.qaevent.AutomaticProcessingAction; import org.dspace.qaevent.AutomaticProcessingAction;
import org.dspace.qaevent.QAEventAutomaticProcessingEvaluation; import org.dspace.qaevent.QAEventAutomaticProcessingEvaluation;
import org.dspace.qaevent.QASource; import org.dspace.qaevent.QASource;
@@ -60,8 +63,6 @@ import org.dspace.qaevent.service.QAEventSecurityService;
import org.dspace.qaevent.service.QAEventService; import org.dspace.qaevent.service.QAEventService;
import org.dspace.services.ConfigurationService; import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.services.factory.DSpaceServicesFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@@ -77,7 +78,9 @@ import org.springframework.beans.factory.annotation.Qualifier;
*/ */
public class QAEventServiceImpl implements QAEventService { public class QAEventServiceImpl implements QAEventService {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(QAEventServiceImpl.class); private static final Logger log = LogManager.getLogger(QAEventServiceImpl.class);
public static final String QAEVENTS_SOURCES = "qaevents.sources";
@Autowired(required = true) @Autowired(required = true)
protected ConfigurationService configurationService; protected ConfigurationService configurationService;
@@ -88,6 +91,9 @@ public class QAEventServiceImpl implements QAEventService {
@Autowired(required = true) @Autowired(required = true)
protected ItemService itemService; protected ItemService itemService;
@Autowired
private HandleService handleService;
@Autowired @Autowired
private QAEventsDAOImpl qaEventsDao; private QAEventsDAOImpl qaEventsDao;
@@ -131,20 +137,13 @@ public class QAEventServiceImpl implements QAEventService {
} }
@Override @Override
public long countTopicsBySource(Context context, String source) { public long countTopics() {
if (isNotSupportedSource(source)
|| !qaSecurityService.canSeeSource(context, context.getCurrentUser(), source)) {
return 0;
}
SolrQuery solrQuery = new SolrQuery(); SolrQuery solrQuery = new SolrQuery();
solrQuery.setRows(0); solrQuery.setRows(0);
Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context, solrQuery.setQuery("*:*");
context.getCurrentUser(), source);
solrQuery.setQuery(securityQuery.orElse("*:*"));
solrQuery.setFacet(true); solrQuery.setFacet(true);
solrQuery.setFacetMinCount(1); solrQuery.setFacetMinCount(1);
solrQuery.addFacetField(TOPIC); solrQuery.addFacetField(TOPIC);
solrQuery.addFilterQuery(SOURCE + ":\"" + source + "\"");
QueryResponse response; QueryResponse response;
try { try {
response = getSolr().query(solrQuery); response = getSolr().query(solrQuery);
@@ -167,7 +166,7 @@ public class QAEventServiceImpl implements QAEventService {
solrQuery.setFacet(true); solrQuery.setFacet(true);
solrQuery.setFacetMinCount(1); solrQuery.setFacetMinCount(1);
solrQuery.addFacetField(TOPIC); solrQuery.addFacetField(TOPIC);
solrQuery.addFilterQuery("source:" + sourceName); solrQuery.addFilterQuery(SOURCE + ":\"" + sourceName + "\"");
QueryResponse response; QueryResponse response;
try { try {
response = getSolr().query(solrQuery); response = getSolr().query(solrQuery);
@@ -178,15 +177,18 @@ public class QAEventServiceImpl implements QAEventService {
} }
@Override @Override
public QATopic findTopicBySourceAndNameAndTarget(Context context, String sourceName, String topicName,UUID target) { public QATopic findTopicBySourceAndNameAndTarget(Context context, String sourceName, String topicName,
var currentUser = context.getCurrentUser(); UUID target) {
if (isNotSupportedSource(sourceName) || !qaSecurityService.canSeeSource(context, currentUser, sourceName)) { if (isNotSupportedSource(sourceName)
|| !qaSecurityService.canSeeSource(context, context.getCurrentUser(), sourceName)) {
return null; return null;
} }
SolrQuery solrQuery = new SolrQuery(); SolrQuery solrQuery = new SolrQuery();
Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context, currentUser, sourceName);
solrQuery.setRows(0); solrQuery.setRows(0);
Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context,
context.getCurrentUser(), sourceName);
solrQuery.setQuery(securityQuery.orElse("*:*")); solrQuery.setQuery(securityQuery.orElse("*:*"));
solrQuery.addFilterQuery(SOURCE + ":\"" + sourceName + "\""); solrQuery.addFilterQuery(SOURCE + ":\"" + sourceName + "\"");
solrQuery.addFilterQuery(TOPIC + ":\"" + topicName + "\""); solrQuery.addFilterQuery(TOPIC + ":\"" + topicName + "\"");
if (target != null) { if (target != null) {
@@ -236,23 +238,10 @@ public class QAEventServiceImpl implements QAEventService {
} }
@Override @Override
public QATopic findTopicBySourceAndNameAndTarget(Context context, String sourceName, String topicName, public QATopic findTopicByTopicId(String topicId) {
UUID target) {
if (isNotSupportedSource(sourceName)
|| !qaSecurityService.canSeeSource(context, context.getCurrentUser(), sourceName)) {
return null;
}
SolrQuery solrQuery = new SolrQuery(); SolrQuery solrQuery = new SolrQuery();
solrQuery.setRows(0); solrQuery.setRows(0);
Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context, solrQuery.setQuery(TOPIC + ":" + topicId.replaceAll("!", "/"));
context.getCurrentUser(), sourceName);
solrQuery.setQuery(securityQuery.orElse("*:*"));
solrQuery.addFilterQuery(SOURCE + ":\"" + sourceName + "\"");
solrQuery.addFilterQuery(TOPIC + ":\"" + topicName + "\"");
if (target != null) {
solrQuery.addFilterQuery(RESOURCE_UUID + ":\"" + target.toString() + "\"");
}
solrQuery.setFacet(true); solrQuery.setFacet(true);
solrQuery.setFacetMinCount(1); solrQuery.setFacetMinCount(1);
solrQuery.addFacetField(TOPIC); solrQuery.addFacetField(TOPIC);
@@ -261,9 +250,8 @@ public class QAEventServiceImpl implements QAEventService {
response = getSolr().query(solrQuery); response = getSolr().query(solrQuery);
FacetField facetField = response.getFacetField(TOPIC); FacetField facetField = response.getFacetField(TOPIC);
for (Count c : facetField.getValues()) { for (Count c : facetField.getValues()) {
if (c.getName().equals(topicName)) { if (c.getName().equals(topicId.replace("!", "/"))) {
QATopic topic = new QATopic(); QATopic topic = new QATopic();
topic.setSource(sourceName);
topic.setKey(c.getName()); topic.setKey(c.getName());
topic.setTotalEvents(c.getCount()); topic.setTotalEvents(c.getCount());
topic.setLastEvent(new Date()); topic.setLastEvent(new Date());
@@ -289,7 +277,7 @@ public class QAEventServiceImpl implements QAEventService {
@Override @Override
public List<QATopic> findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset, public List<QATopic> findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset,
long count, String orderField, boolean ascending) { long pageSize, String orderField, boolean ascending) {
if (isNotSupportedSource(source) if (isNotSupportedSource(source)
|| !qaSecurityService.canSeeSource(context, context.getCurrentUser(), source)) { || !qaSecurityService.canSeeSource(context, context.getCurrentUser(), source)) {
return List.of(); return List.of();
@@ -305,7 +293,7 @@ public class QAEventServiceImpl implements QAEventService {
solrQuery.setQuery(securityQuery.orElse("*:*")); solrQuery.setQuery(securityQuery.orElse("*:*"));
solrQuery.setFacet(true); solrQuery.setFacet(true);
solrQuery.setFacetMinCount(1); solrQuery.setFacetMinCount(1);
solrQuery.setFacetLimit((int) (offset + count)); solrQuery.setFacetLimit((int) (offset + pageSize));
solrQuery.addFacetField(TOPIC); solrQuery.addFacetField(TOPIC);
solrQuery.addFilterQuery(SOURCE + ":\"" + source + "\""); solrQuery.addFilterQuery(SOURCE + ":\"" + source + "\"");
if (target != null) { if (target != null) {
@@ -453,76 +441,39 @@ public class QAEventServiceImpl implements QAEventService {
} }
@Override @Override
public List<QAEvent> findEventsByTopicAndPage(Context context, String source, String topic, long offset, public List<QAEvent> findEventsByTopic(Context context, String sourceName, String topic, long offset, int pageSize,
int pageSize) { String orderField, boolean ascending) {
if (isNotSupportedSource(source) EPerson currentUser = context.getCurrentUser();
|| !qaSecurityService.canSeeSource(context, context.getCurrentUser(), source)) { if (isNotSupportedSource(sourceName) || !qaSecurityService.canSeeSource(context, currentUser, sourceName)) {
return List.of(); return List.of();
} }
SolrQuery solrQuery = new SolrQuery(); SolrQuery solrQuery = new SolrQuery();
solrQuery.setStart(((Long) offset).intValue()); solrQuery.setStart(((Long) offset).intValue());
if (pageSize != -1) { if (pageSize != -1) {
solrQuery.setRows(pageSize); solrQuery.setRows(pageSize);
} }
solrQuery.setSort(TRUST, ORDER.desc); solrQuery.setSort(orderField, ascending ? ORDER.asc : ORDER.desc);
solrQuery.addFilterQuery(SOURCE + ":\"" + source + "\""); Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context, currentUser, sourceName);
solrQuery.setQuery(TOPIC + ":\"" + topic + "\"");
QueryResponse response;
try {
response = getSolr().query(solrQuery);
if (response != null) {
SolrDocumentList list = response.getResults();
List<QAEvent> responseItem = new ArrayList<>();
for (SolrDocument doc : list) {
QAEvent item = getQAEventFromSOLR(doc);
responseItem.add(item);
}
return responseItem;
}
} catch (SolrServerException | IOException e) {
throw new RuntimeException(e);
}
return List.of();
}
@Override
public List<QAEvent> findEventsByTopicAndPageAndTarget(Context context, String source, String topic, long offset,
int pageSize, UUID target) {
if (isNotSupportedSource(source)
|| !qaSecurityService.canSeeSource(context, context.getCurrentUser(), source)) {
return List.of();
}
SolrQuery solrQuery = new SolrQuery();
solrQuery.setStart(((Long) offset).intValue());
solrQuery.setRows(pageSize);
solrQuery.setSort(TRUST, ORDER.desc);
Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context,
context.getCurrentUser(), source);
solrQuery.setQuery(securityQuery.orElse("*:*")); solrQuery.setQuery(securityQuery.orElse("*:*"));
if (target != null) {
solrQuery.addFilterQuery(RESOURCE_UUID + ":\"" + target.toString() + "\"");
}
solrQuery.addFilterQuery(SOURCE + ":\"" + source + "\"");
solrQuery.addFilterQuery(TOPIC + ":\"" + topic + "\"");
QueryResponse response; solrQuery.setQuery(TOPIC + ":" + topic.replaceAll("!", "/"));
solrQuery.addFilterQuery(SOURCE + ":\"" + sourceName + "\"");
try { try {
response = getSolr().query(solrQuery); QueryResponse response = getSolr().query(solrQuery);
if (response != null) { if (response != null) {
SolrDocumentList list = response.getResults(); SolrDocumentList solrDocuments = response.getResults();
List<QAEvent> responseItem = new ArrayList<>(); List<QAEvent> responseItem = new ArrayList<>();
for (SolrDocument doc : list) { for (SolrDocument doc : solrDocuments) {
QAEvent item = getQAEventFromSOLR(doc); QAEvent item = getQAEventFromSOLR(doc);
responseItem.add(item); responseItem.add(item);
} }
return responseItem; return responseItem;
} }
} catch (SolrServerException | IOException e) { } catch (SolrServerException | IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e.getMessage(), e);
} }
return List.of(); return List.of();
} }
@@ -618,18 +569,6 @@ public class QAEventServiceImpl implements QAEventService {
.count(); .count();
} }
@Override
public List<QASource> findAllSourcesByTarget(Context context, UUID target, long offset, int pageSize) {
return Arrays.stream(getSupportedSources())
.map((sourceName) -> findSource(context, sourceName, target))
.filter(Objects::nonNull)
.sorted(comparing(QASource::getTotalEvents).reversed())
.filter(source -> source.getTotalEvents() > 0)
.skip(offset)
.limit(pageSize)
.collect(Collectors.toList());
}
@Override @Override
public long countSourcesByTarget(Context context, UUID target) { public long countSourcesByTarget(Context context, UUID target) {
return Arrays.stream(getSupportedSources()) return Arrays.stream(getSupportedSources())
@@ -655,7 +594,12 @@ public class QAEventServiceImpl implements QAEventService {
doc.addField(TRUST, dto.getTrust()); doc.addField(TRUST, dto.getTrust());
doc.addField(MESSAGE, dto.getMessage()); doc.addField(MESSAGE, dto.getMessage());
doc.addField(LAST_UPDATE, new Date()); doc.addField(LAST_UPDATE, new Date());
doc.addField(RESOURCE_UUID, dto.getTarget()); final String resourceUUID = getResourceUUID(context, dto.getOriginalId());
if (resourceUUID == null) {
throw new IllegalArgumentException("Skipped event " + checksum +
" related to the oai record " + dto.getOriginalId() + " as the record was not found");
}
doc.addField(RESOURCE_UUID, resourceUUID);
doc.addField(RELATED_UUID, dto.getRelated()); doc.addField(RELATED_UUID, dto.getRelated());
return doc; return doc;
} }
@@ -825,49 +769,4 @@ public class QAEventServiceImpl implements QAEventService {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override
public List<QATopic> findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset,
int pageSize, String orderField, boolean ascending) {
var currentUser = context.getCurrentUser();
if (isNotSupportedSource(source) || !qaSecurityService.canSeeSource(context, currentUser, source)) {
return List.of();
}
Optional<String> securityQuery = qaSecurityService.generateQAEventFilterQuery(context, currentUser, source);
SolrQuery solrQuery = new SolrQuery();
solrQuery.setRows(0);
solrQuery.setSort(orderField, ascending ? ORDER.asc : ORDER.desc);
solrQuery.setQuery(securityQuery.orElse("*:*"));
solrQuery.setFacet(true);
solrQuery.setFacetMinCount(1);
solrQuery.setFacetLimit((int) (offset + pageSize));
solrQuery.addFacetField(TOPIC);
solrQuery.addFilterQuery(SOURCE + ":\"" + source + "\"");
if (target != null) {
solrQuery.addFilterQuery(RESOURCE_UUID + ":" + target.toString());
}
try {
List<QATopic> topics = new ArrayList<>();
QueryResponse response = getSolr().query(solrQuery);
FacetField facetField = response.getFacetField(TOPIC);
int idx = 0;
for (Count c : facetField.getValues()) {
if (idx < offset) {
idx++;
continue;
}
QATopic topic = new QATopic();
topic.setSource(source);
topic.setKey(c.getName());
topic.setFocus(target);
topic.setTotalEvents(c.getCount());
topic.setLastEvent(new Date());
topics.add(topic);
idx++;
}
return topics;
} catch (SolrServerException | IOException e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -14,6 +14,7 @@ import static org.dspace.matcher.QAEventMatcher.pendingOpenaireEventWith;
import static org.dspace.qaevent.service.impl.QAEventServiceImpl.QAEVENTS_SOURCES; import static org.dspace.qaevent.service.impl.QAEventServiceImpl.QAEVENTS_SOURCES;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
@@ -58,6 +59,7 @@ import org.dspace.services.ConfigurationService;
import org.dspace.utils.DSpace; import org.dspace.utils.DSpace;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
/** /**
@@ -186,8 +188,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
+ "\"projects[0].openaireId\":\"40|corda__h2020::6e32f5eb912688f2424c68b851483ea4\"," + "\"projects[0].openaireId\":\"40|corda__h2020::6e32f5eb912688f2424c68b851483ea4\","
+ "\"projects[0].title\":\"Tracking Papyrus and Parchment Paths\"}"; + "\"projects[0].title\":\"Tracking Papyrus and Parchment Paths\"}";
assertThat(qaEventService.findEventsByTopicAndPage(context, OPENAIRE_SOURCE, assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 0, 20), QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 0, 20, null, true),
contains( contains(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99998", firstItem, pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99998", firstItem,
"Egypt, crossroad of translations and literary interweavings", projectMessage, "Egypt, crossroad of translations and literary interweavings", projectMessage,
@@ -195,8 +197,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}"; String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}";
assertThat(qaEventService.findEventsByTopicAndPage(context, OPENAIRE_SOURCE, assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 0, 20), QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 0, 20, null, true),
contains( contains(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99999", pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99999",
secondItem, "Test Publication", secondItem, "Test Publication",
@@ -241,7 +243,9 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}"; String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}";
assertThat(qaEventService.findEventsByTopic("ENRICH/MISSING/ABSTRACT"), contains( assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 0, 20,
ORDER_FIELD, false), contains(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99999", item, "Test Publication", pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99999", item, "Test Publication",
abstractMessage, QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d))); abstractMessage, QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d)));
@@ -279,7 +283,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}"; String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}";
assertThat(qaEventService.findEventsByTopic("ENRICH/MISSING/ABSTRACT"), contains( assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 0, 20, ORDER_FIELD, false), contains(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/999991", secondItem, "Test Publication 2", pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/999991", secondItem, "Test Publication 2",
abstractMessage, org.dspace.qaevent.QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d))); abstractMessage, org.dspace.qaevent.QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d)));
@@ -301,7 +306,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 0L))); assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 0L)));
assertThat(qaEventService.findAllTopics(0, 20, ORDER_FIELD, false), empty()); assertThat(qaEventService.findAllTopics(context, 0, 20, ORDER_FIELD, false), empty());
verifyNoInteractions(mockBrokerClient); verifyNoInteractions(mockBrokerClient);
} }
@@ -347,8 +352,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 6L))); assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 6L)));
List<QATopic> topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, List<QATopic> topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE,0,20,ORDER_FIELD,false);
ORDER_FIELD, false);
assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1L)));
assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PID, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PID, 1L)));
assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PID, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PID, 1L)));
@@ -361,17 +365,20 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
+ "\"projects[0].openaireId\":\"40|corda__h2020::6e32f5eb912688f2424c68b851483ea4\"," + "\"projects[0].openaireId\":\"40|corda__h2020::6e32f5eb912688f2424c68b851483ea4\","
+ "\"projects[0].title\":\"Tracking Papyrus and Parchment Paths\"}"; + "\"projects[0].title\":\"Tracking Papyrus and Parchment Paths\"}";
assertThat(qaEventService.findEventsByTopic("ENRICH/MORE/PROJECT"), contains( assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 0 , 20,
ORDER_FIELD, false), contains(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99998", firstItem, pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99998", firstItem,
"Egypt, crossroad of translations and literary interweavings", projectMessage, "Egypt, crossroad of translations and literary interweavings", projectMessage,
QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1.00d))); QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1.00d)));
String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}"; String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}";
assertThat(qaEventService.findEventsByTopic("ENRICH/MISSING/ABSTRACT"), containsInAnyOrder( assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 0, 20,
ORDER_FIELD, false), containsInAnyOrder(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99999", secondItem, "Test Publication", pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/99999", secondItem, "Test Publication",
abstractMessage, QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d))); abstractMessage, QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d),
assertThat(eventList, hasItem(
pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/999991", thirdItem, "Test Publication 2", pendingOpenaireEventWith("oai:www.openstarts.units.it:123456789/999991", thirdItem, "Test Publication 2",
abstractMessage, QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d))); abstractMessage, QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1.00d)));
@@ -403,7 +410,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 0L))); assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 0L)));
assertThat(qaEventService.findAllTopics(0, 20, ORDER_FIELD, false), empty()); assertThat(qaEventService.findAllTopics(context, 0, 20, ORDER_FIELD, false), empty());
verify(mockBrokerClient).listSubscriptions(openaireURL, "user@test.com"); verify(mockBrokerClient).listSubscriptions(openaireURL, "user@test.com");
@@ -461,8 +468,10 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PROJECT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PROJECT, 1L)));
assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 2L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 2L)));
assertThat(qaEventService.findEventsByTopic("ENRICH/MORE/PROJECT"), hasSize(1)); assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
assertThat(qaEventService.findEventsByTopic("ENRICH/MISSING/ABSTRACT"), hasSize(2)); QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 0, 20, ORDER_FIELD, false), hasSize(1));
assertThat(qaEventService.findEventsByTopic(context, OPENAIRE_SOURCE,
QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 0, 20, ORDER_FIELD, false), hasSize(2));
verify(mockBrokerClient).listSubscriptions(openaireURL, "user@test.com"); verify(mockBrokerClient).listSubscriptions(openaireURL, "user@test.com");
verify(mockBrokerClient).downloadEvents(eq(openaireURL), eq("sub1"), any()); verify(mockBrokerClient).downloadEvents(eq(openaireURL), eq("sub1"), any());
@@ -474,7 +483,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase
/** /**
* Improper test for ENRICH/MORE/REVIEW qa. It has the COAR_NOTIFY source * Improper test for ENRICH/MORE/REVIEW qa. It has the COAR_NOTIFY source
* which must be tested via LDNMessage {@link LDNInboxControllerIT} * which must be tested via LDNMessage at DNInboxControllerIT
*/ */
@Test @Test
@Ignore @Ignore

View File

@@ -78,7 +78,7 @@ public class QAEventRelatedRestController {
@RequestParam(name = "item") UUID relatedItemUUID) throws SQLException, AuthorizeException { @RequestParam(name = "item") UUID relatedItemUUID) throws SQLException, AuthorizeException {
Context context = ContextUtil.obtainCurrentRequestContext(); Context context = ContextUtil.obtainCurrentRequestContext();
QAEvent qaevent = qaEventService.findEventByEventId(context, qaeventId); QAEvent qaevent = qaEventService.findEventByEventId(qaeventId);
if (qaevent == null) { if (qaevent == null) {
throw new ResourceNotFoundException("No such qa event: " + qaeventId); throw new ResourceNotFoundException("No such qa event: " + qaeventId);
} }
@@ -121,7 +121,7 @@ public class QAEventRelatedRestController {
throws SQLException, AuthorizeException, IOException { throws SQLException, AuthorizeException, IOException {
Context context = ContextUtil.obtainCurrentRequestContext(); Context context = ContextUtil.obtainCurrentRequestContext();
QAEvent qaevent = qaEventService.findEventByEventId(context, qaeventId); QAEvent qaevent = qaEventService.findEventByEventId(qaeventId);
if (qaevent == null) { if (qaevent == null) {
throw new ResourceNotFoundException("No such qa event: " + qaeventId); throw new ResourceNotFoundException("No such qa event: " + qaeventId);

View File

@@ -16,15 +16,15 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.json.JsonMapper;
import org.dspace.app.rest.model.NotifyQAEventMessageRest;
import org.dspace.app.rest.model.CorrectionTypeQAEventMessageRest; import org.dspace.app.rest.model.CorrectionTypeQAEventMessageRest;
import org.dspace.app.rest.model.NotifyQAEventMessageRest;
import org.dspace.app.rest.model.OpenaireQAEventMessageRest; import org.dspace.app.rest.model.OpenaireQAEventMessageRest;
import org.dspace.app.rest.model.QAEventMessageRest; import org.dspace.app.rest.model.QAEventMessageRest;
import org.dspace.app.rest.model.QAEventRest; import org.dspace.app.rest.model.QAEventRest;
import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.projection.Projection;
import org.dspace.content.QAEvent; import org.dspace.content.QAEvent;
import org.dspace.qaevent.service.dto.NotifyMessageDTO;
import org.dspace.qaevent.service.dto.CorrectionTypeMessageDTO; import org.dspace.qaevent.service.dto.CorrectionTypeMessageDTO;
import org.dspace.qaevent.service.dto.NotifyMessageDTO;
import org.dspace.qaevent.service.dto.OpenaireMessageDTO; import org.dspace.qaevent.service.dto.OpenaireMessageDTO;
import org.dspace.qaevent.service.dto.QAMessageDTO; import org.dspace.qaevent.service.dto.QAMessageDTO;
import org.dspace.services.ConfigurationService; import org.dspace.services.ConfigurationService;

View File

@@ -55,7 +55,7 @@ public class QAEventRelatedLinkRepository extends AbstractDSpaceRestRepository i
public ItemRest getRelated(@Nullable HttpServletRequest request, String id, @Nullable Pageable pageable, public ItemRest getRelated(@Nullable HttpServletRequest request, String id, @Nullable Pageable pageable,
Projection projection) { Projection projection) {
Context context = obtainContext(); Context context = obtainContext();
QAEvent qaEvent = qaEventService.findEventByEventId(context, id); QAEvent qaEvent = qaEventService.findEventByEventId(id);
if (qaEvent == null) { if (qaEvent == null) {
throw new ResourceNotFoundException("No qa event with ID: " + id); throw new ResourceNotFoundException("No qa event with ID: " + id);
} }

View File

@@ -10,7 +10,9 @@ package org.dspace.app.rest.repository;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -74,7 +76,7 @@ public class QAEventRestRepository extends DSpaceRestRepository<QAEventRest, Str
@Override @Override
@PreAuthorize("hasPermission(#id, 'QUALITYASSURANCEEVENT', 'READ')") @PreAuthorize("hasPermission(#id, 'QUALITYASSURANCEEVENT', 'READ')")
public QAEventRest findOne(Context context, String id) { public QAEventRest findOne(Context context, String id) {
QAEvent qaEvent = qaEventService.findEventByEventId(context, id); QAEvent qaEvent = qaEventService.findEventByEventId(id);
if (qaEvent == null) { if (qaEvent == null) {
// check if this request is part of a patch flow // check if this request is part of a patch flow
qaEvent = (QAEvent) requestService.getCurrentRequest().getAttribute("patchedNotificationEvent"); qaEvent = (QAEvent) requestService.getCurrentRequest().getAttribute("patchedNotificationEvent");
@@ -99,8 +101,8 @@ public class QAEventRestRepository extends DSpaceRestRepository<QAEventRest, Str
String sourceName = topicIdSplitted[0]; String sourceName = topicIdSplitted[0];
String topicName = topicIdSplitted[1].replaceAll("!", "/"); String topicName = topicIdSplitted[1].replaceAll("!", "/");
UUID target = topicIdSplitted.length == 3 ? UUID.fromString(topicIdSplitted[2]) : null; UUID target = topicIdSplitted.length == 3 ? UUID.fromString(topicIdSplitted[2]) : null;
List<QAEvent> qaEvents = qaEventService.findEventsByTopicAndPageAndTarget(context, sourceName, topicName, List<QAEvent> qaEvents = qaEventService.findEventsByTopicAndTarget(context, sourceName, topicName, target,
pageable.getOffset(), pageable.getPageSize(), target); pageable.getOffset(), pageable.getPageSize());
long count = qaEventService.countEventsByTopicAndTarget(context, sourceName, topicName, target); long count = qaEventService.countEventsByTopicAndTarget(context, sourceName, topicName, target);
if (qaEvents == null) { if (qaEvents == null) {
return null; return null;
@@ -121,12 +123,12 @@ public class QAEventRestRepository extends DSpaceRestRepository<QAEventRest, Str
@PreAuthorize("hasPermission(#id, 'QUALITYASSURANCEEVENT', 'WRITE')") @PreAuthorize("hasPermission(#id, 'QUALITYASSURANCEEVENT', 'WRITE')")
protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, protected void patch(Context context, HttpServletRequest request, String apiCategory, String model,
String id, Patch patch) throws SQLException, AuthorizeException { String id, Patch patch) throws SQLException, AuthorizeException {
QAEvent qaEvent = qaEventService.findEventByEventId(context, id); QAEvent qaEvent = qaEventService.findEventByEventId(id);
resourcePatch.patch(context, qaEvent, patch.getOperations()); resourcePatch.patch(context, qaEvent, patch.getOperations());
} }
private Item findTargetItem(Context context, String eventId) { private Item findTargetItem(Context context, String eventId) {
QAEvent qaEvent = qaEventService.findEventByEventId(context, eventId); QAEvent qaEvent = qaEventService.findEventByEventId(eventId);
if (qaEvent == null) { if (qaEvent == null) {
return null; return null;
} }

View File

@@ -54,7 +54,7 @@ public class QAEventTargetLinkRepository extends AbstractDSpaceRestRepository im
public ItemRest getTarget(@Nullable HttpServletRequest request, String id, @Nullable Pageable pageable, public ItemRest getTarget(@Nullable HttpServletRequest request, String id, @Nullable Pageable pageable,
Projection projection) { Projection projection) {
Context context = obtainContext(); Context context = obtainContext();
QAEvent qaEvent = qaEventService.findEventByEventId(context, id); QAEvent qaEvent = qaEventService.findEventByEventId(id);
if (qaEvent == null) { if (qaEvent == null) {
throw new ResourceNotFoundException("No qa event with ID: " + id); throw new ResourceNotFoundException("No qa event with ID: " + id);
} }

View File

@@ -48,7 +48,7 @@ public class QAEventTopicLinkRepository extends AbstractDSpaceRestRepository imp
public QATopicRest getTopic(@Nullable HttpServletRequest request, String id, @Nullable Pageable pageable, public QATopicRest getTopic(@Nullable HttpServletRequest request, String id, @Nullable Pageable pageable,
Projection projection) { Projection projection) {
Context context = obtainContext(); Context context = obtainContext();
QAEvent qaEvent = qaEventService.findEventByEventId(context, id); QAEvent qaEvent = qaEventService.findEventByEventId(id);
if (qaEvent == null) { if (qaEvent == null) {
throw new ResourceNotFoundException("No qa event with ID: " + id); throw new ResourceNotFoundException("No qa event with ID: " + id);
} }

View File

@@ -91,6 +91,12 @@ public class QATopicRestRepository extends DSpaceRestRepository<QATopicRest, Str
List<QATopic> topics = qaEventService.findAllTopicsBySourceAndTarget(context, source, target, List<QATopic> topics = qaEventService.findAllTopicsBySourceAndTarget(context, source, target,
pageable.getOffset(), pageable.getPageSize(), ORDER_FIELD, ascending); pageable.getOffset(), pageable.getPageSize(), ORDER_FIELD, ascending);
long count = qaEventService.countTopicsBySourceAndTarget(context, source, target); long count = qaEventService.countTopicsBySourceAndTarget(context, source, target);
if (topics == null) {
return null;
}
return converter.toRestPage(topics, pageable, count, utils.obtainProjection());
}
@Override @Override
public Class<QATopicRest> getDomainClass() { public Class<QATopicRest> getDomainClass() {
return QATopicRest.class; return QATopicRest.class;

View File

@@ -61,7 +61,7 @@ public class QAEventRestPermissionEvaluatorPlugin extends RestObjectPermissionEv
if (Objects.isNull(targetId)) { if (Objects.isNull(targetId)) {
return true; return true;
} }
QAEvent qaEvent = qaEventService.findEventByEventId(context, targetId.toString()); QAEvent qaEvent = qaEventService.findEventByEventId(targetId.toString());
// everyone is expected to be able to see a not existing event (so we can return not found) // everyone is expected to be able to see a not existing event (so we can return not found)
if ((qaEvent == null if ((qaEvent == null
|| qaEventSecurityService.canSeeEvent(context, context.getCurrentUser(), qaEvent))) { || qaEventSecurityService.canSeeEvent(context, context.getCurrentUser(), qaEvent))) {

View File

@@ -72,9 +72,12 @@ public class NotifyServiceAddPatchOperation extends AddPatchOperation<Integer> {
.map(id -> .map(id ->
findService(context, id)) findService(context, id))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (services.isEmpty()) {
services.forEach(service -> createNotifyPattern(context, source.getItem(), null, pattern);
createNotifyPattern(context, source.getItem(), service, pattern)); } else {
services.forEach(service ->
createNotifyPattern(context, source.getItem(), service, pattern));
}
} }
private NotifyServiceEntity findService(Context context, int serviceId) { private NotifyServiceEntity findService(Context context, int serviceId) {

View File

@@ -11,7 +11,6 @@ import static com.jayway.jsonpath.JsonPath.read;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;
import static org.dspace.content.QAEvent.COAR_NOTIFY_SOURCE; import static org.dspace.content.QAEvent.COAR_NOTIFY_SOURCE;
import static org.dspace.content.QAEvent.OPENAIRE_SOURCE;
import static org.dspace.content.QAEvent.DSPACE_USERS_SOURCE; import static org.dspace.content.QAEvent.DSPACE_USERS_SOURCE;
import static org.dspace.content.QAEvent.OPENAIRE_SOURCE; import static org.dspace.content.QAEvent.OPENAIRE_SOURCE;
import static org.dspace.correctiontype.WithdrawnCorrectionType.WITHDRAWAL_REINSTATE_GROUP; import static org.dspace.correctiontype.WithdrawnCorrectionType.WITHDRAWAL_REINSTATE_GROUP;
@@ -36,8 +35,8 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.dspace.app.ldn.NotifyServiceEntity;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.ldn.NotifyServiceEntity;
import org.dspace.app.rest.matcher.ItemMatcher; import org.dspace.app.rest.matcher.ItemMatcher;
import org.dspace.app.rest.matcher.MetadataMatcher; import org.dspace.app.rest.matcher.MetadataMatcher;
import org.dspace.app.rest.matcher.QAEventMatcher; import org.dspace.app.rest.matcher.QAEventMatcher;
@@ -61,6 +60,7 @@ import org.dspace.content.QAEvent;
import org.dspace.content.QAEventProcessed; import org.dspace.content.QAEventProcessed;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.qaevent.QANotifyPatterns; import org.dspace.qaevent.QANotifyPatterns;
import org.dspace.qaevent.action.ASimpleMetadataAction; import org.dspace.qaevent.action.ASimpleMetadataAction;
import org.dspace.qaevent.dao.QAEventsDAO; import org.dspace.qaevent.dao.QAEventsDAO;
@@ -446,7 +446,8 @@ public class QAEventRestRepositoryIT extends AbstractControllerIntegrationTest {
get("/api/integration/qualityassuranceevents/search/findByTopic") get("/api/integration/qualityassuranceevents/search/findByTopic")
.param("topic", QAEvent.OPENAIRE_SOURCE + ":ENRICH!MISSING!PID") .param("topic", QAEvent.OPENAIRE_SOURCE + ":ENRICH!MISSING!PID")
.param("size", "2")) .param("size", "2"))
.andExpect(status().isOk()).andExpect(jsonPath("$._embedded.qualityassuranceevents", Matchers.hasSize(2))) .andExpect(status().isOk()).andExpect(
jsonPath("$._embedded.qualityassuranceevents", Matchers.hasSize(2)))
.andExpect(jsonPath("$._embedded.qualityassuranceevents", .andExpect(jsonPath("$._embedded.qualityassuranceevents",
Matchers.containsInAnyOrder( Matchers.containsInAnyOrder(
QAEventMatcher.matchQAEventEntry(event1), QAEventMatcher.matchQAEventEntry(event1),
@@ -484,7 +485,8 @@ public class QAEventRestRepositoryIT extends AbstractControllerIntegrationTest {
get("/api/integration/qualityassuranceevents/search/findByTopic") get("/api/integration/qualityassuranceevents/search/findByTopic")
.param("topic", QAEvent.OPENAIRE_SOURCE + ":ENRICH!MISSING!PID") .param("topic", QAEvent.OPENAIRE_SOURCE + ":ENRICH!MISSING!PID")
.param("size", "2").param("page", "1")) .param("size", "2").param("page", "1"))
.andExpect(status().isOk()).andExpect(jsonPath("$._embedded.qualityassuranceevents", Matchers.hasSize(2))) .andExpect(status().isOk()).andExpect(
jsonPath("$._embedded.qualityassuranceevents", Matchers.hasSize(2)))
.andExpect(jsonPath("$._embedded.qualityassuranceevents", .andExpect(jsonPath("$._embedded.qualityassuranceevents",
Matchers.containsInAnyOrder( Matchers.containsInAnyOrder(
QAEventMatcher.matchQAEventEntry(event3), QAEventMatcher.matchQAEventEntry(event3),
@@ -528,7 +530,8 @@ public class QAEventRestRepositoryIT extends AbstractControllerIntegrationTest {
get("/api/integration/qualityassuranceevents/search/findByTopic") get("/api/integration/qualityassuranceevents/search/findByTopic")
.param("topic", QAEvent.OPENAIRE_SOURCE + ":ENRICH!MISSING!PID") .param("topic", QAEvent.OPENAIRE_SOURCE + ":ENRICH!MISSING!PID")
.param("size", "2").param("page", "2")) .param("size", "2").param("page", "2"))
.andExpect(status().isOk()).andExpect(jsonPath("$._embedded.qualityassuranceevents", Matchers.hasSize(2))) .andExpect(status().isOk()).andExpect(
jsonPath("$._embedded.qualityassuranceevents", Matchers.hasSize(2)))
.andExpect(jsonPath("$._embedded.qualityassuranceevents", .andExpect(jsonPath("$._embedded.qualityassuranceevents",
Matchers.hasItem( Matchers.hasItem(
QAEventMatcher.matchQAEventEntry(event5)))) QAEventMatcher.matchQAEventEntry(event5))))

View File

@@ -62,17 +62,18 @@ public class QASourceRestRepositoryIT extends AbstractControllerIntegrationTest
context.restoreAuthSystemState(); context.restoreAuthSystemState();
configurationService.setProperty(QAEVENTS_SOURCES, new String[] { "openaire","coar-notify", "test-source","test-source-2" }); configurationService.setProperty(QAEVENTS_SOURCES,
new String[] { QAEvent.OPENAIRE_SOURCE,"coar-notify", "test-source","test-source-2" });
} }
@Test @Test
public void testFindAll() throws Exception { public void testFindAll() throws Exception {
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
createEvent("openaire", "TOPIC/OPENAIRE/1", "Title 1"); createEvent(QAEvent.OPENAIRE_SOURCE, "TOPIC/OPENAIRE/1", "Title 1");
createEvent("openaire", "TOPIC/OPENAIRE/2", "Title 2"); createEvent(QAEvent.OPENAIRE_SOURCE, "TOPIC/OPENAIRE/2", "Title 2");
context.setCurrentUser(eperson); context.setCurrentUser(eperson);
createEvent("openaire", "TOPIC/OPENAIRE/2", "Title 3"); createEvent(QAEvent.OPENAIRE_SOURCE, "TOPIC/OPENAIRE/2", "Title 3");
createEvent("openaire", "TOPIC/OPENAIRE/2", "Title 4"); createEvent(QAEvent.OPENAIRE_SOURCE, "TOPIC/OPENAIRE/2", "Title 4");
createEvent("test-source", "TOPIC/TEST/1", "Title 5"); createEvent("test-source", "TOPIC/TEST/1", "Title 5");
createEvent("test-source", "TOPIC/TEST/1", "Title 6"); createEvent("test-source", "TOPIC/TEST/1", "Title 6");
@@ -88,7 +89,7 @@ public class QASourceRestRepositoryIT extends AbstractControllerIntegrationTest
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(contentType)) .andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.qualityassurancesources", contains( .andExpect(jsonPath("$._embedded.qualityassurancesources", contains(
matchQASourceEntry("openaire", 4), matchQASourceEntry(QAEvent.OPENAIRE_SOURCE, 4),
matchQASourceEntry("coar-notify", 3), matchQASourceEntry("coar-notify", 3),
matchQASourceEntry("test-source", 2), matchQASourceEntry("test-source", 2),
matchQASourceEntry("test-source-2", 0)))) matchQASourceEntry("test-source-2", 0))))
@@ -110,7 +111,7 @@ public class QASourceRestRepositoryIT extends AbstractControllerIntegrationTest
public void testFindAllUnauthorized() throws Exception { public void testFindAllUnauthorized() throws Exception {
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
createEvent("openaire", "TOPIC/OPENAIRE/1", "Title 1"); createEvent(QAEvent.OPENAIRE_SOURCE, "TOPIC/OPENAIRE/1", "Title 1");
createEvent("test-source", "TOPIC/TEST/1", "Title 4"); createEvent("test-source", "TOPIC/TEST/1", "Title 4");
context.restoreAuthSystemState(); context.restoreAuthSystemState();
@@ -145,7 +146,7 @@ public class QASourceRestRepositoryIT extends AbstractControllerIntegrationTest
getClient(authToken).perform(get("/api/integration/qualityassurancesources/openaire")) getClient(authToken).perform(get("/api/integration/qualityassurancesources/openaire"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(contentType)) .andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", matchQASourceEntry("openaire", 3))); .andExpect(jsonPath("$", matchQASourceEntry(QAEvent.OPENAIRE_SOURCE, 3)));
getClient(authToken).perform(get("/api/integration/qualityassurancesources/coar-notify")) getClient(authToken).perform(get("/api/integration/qualityassurancesources/coar-notify"))
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -185,7 +186,7 @@ public class QASourceRestRepositoryIT extends AbstractControllerIntegrationTest
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
createEvent("openaire", "TOPIC/OPENAIRE/1", "Title 1"); createEvent(QAEvent.OPENAIRE_SOURCE, "TOPIC/OPENAIRE/1", "Title 1");
createEvent("test-source", "TOPIC/TEST/1", "Title 4"); createEvent("test-source", "TOPIC/TEST/1", "Title 4");
context.restoreAuthSystemState(); context.restoreAuthSystemState();

View File

@@ -106,7 +106,7 @@ public class QATopicRestRepositoryIT extends AbstractControllerIntegrationTest {
public void findOneNotFoundTest() throws Exception { public void findOneNotFoundTest() throws Exception {
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
configurationService.setProperty("qaevent.sources", configurationService.setProperty("qaevent.sources",
new String[] { "openaire" }); new String[] { QAEvent.OPENAIRE_SOURCE });
parentCommunity = CommunityBuilder.createCommunity(context) parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community") .withName("Parent Community")
.build(); .build();
@@ -241,7 +241,7 @@ public class QATopicRestRepositoryIT extends AbstractControllerIntegrationTest {
public void findBySourcePaginationTest() throws Exception { public void findBySourcePaginationTest() throws Exception {
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
configurationService.setProperty("qaevent.sources", configurationService.setProperty("qaevent.sources",
new String[] { "openaire", "test-source", "test-source-2" }); new String[] { QAEvent.OPENAIRE_SOURCE, "test-source", "test-source-2" });
parentCommunity = CommunityBuilder.createCommunity(context) parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community") .withName("Parent Community")
.build(); .build();
@@ -294,13 +294,14 @@ public class QATopicRestRepositoryIT extends AbstractControllerIntegrationTest {
.andExpect(content().contentType(contentType)) .andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.qualityassurancetopics", Matchers.hasSize(1))) .andExpect(jsonPath("$._embedded.qualityassurancetopics", Matchers.hasSize(1)))
.andExpect(jsonPath("$.page.size", is(2))).andExpect(jsonPath("$.page.totalElements", is(3))); .andExpect(jsonPath("$.page.size", is(2))).andExpect(jsonPath("$.page.totalElements", is(3)));
//test unsupported
getClient(authToken).perform(get("/api/integration/qualityassurancetopics/search/bySource") getClient(authToken).perform(get("/api/integration/qualityassurancetopics/search/bySource")
.param("source", "test-source") .param("source", "test-source")
.param("size", "2")) .param("size", "2"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(contentType)) .andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.qualityassurancetopics", Matchers.hasSize(2))) .andExpect(jsonPath("$._embedded").doesNotExist())
.andExpect(jsonPath("$.page.size", is(2))).andExpect(jsonPath("$.page.totalElements", is(2))); .andExpect(jsonPath("$.page.size", is(2))).andExpect(jsonPath("$.page.totalElements", is(0)));
} }
@Test @Test
@@ -334,7 +335,7 @@ public class QATopicRestRepositoryIT extends AbstractControllerIntegrationTest {
context.restoreAuthSystemState(); context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password); String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(get("/api/integration/qualityassurancetopics/search/bySource") getClient(authToken).perform(get("/api/integration/qualityassurancetopics/search/bySource")
.param("source", "openaire")) .param("source", QAEvent.OPENAIRE_SOURCE))
.andExpect(status().isForbidden()); .andExpect(status().isForbidden());
} }
@@ -342,7 +343,7 @@ public class QATopicRestRepositoryIT extends AbstractControllerIntegrationTest {
public void findByTargetTest() throws Exception { public void findByTargetTest() throws Exception {
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
configurationService.setProperty("qaevent.sources", configurationService.setProperty("qaevent.sources",
new String[] { "openaire", "test-source", "test-source-2" }); new String[] { QAEvent.OPENAIRE_SOURCE, "test-source", "test-source-2" });
parentCommunity = CommunityBuilder.createCommunity(context) parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community") .withName("Parent Community")
.build(); .build();
@@ -391,7 +392,7 @@ public class QATopicRestRepositoryIT extends AbstractControllerIntegrationTest {
.andExpect(jsonPath("$.page.size", is(20))).andExpect(jsonPath("$.page.totalElements", is(2))); .andExpect(jsonPath("$.page.size", is(20))).andExpect(jsonPath("$.page.totalElements", is(2)));
getClient(authToken).perform(get("/api/integration/qualityassurancetopics/search/byTarget") getClient(authToken).perform(get("/api/integration/qualityassurancetopics/search/byTarget")
.param("target", item2.getID().toString()) .param("target", item2.getID().toString())
.param("source", "openaire")) .param("source", QAEvent.OPENAIRE_SOURCE))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(contentType)) .andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.qualityassurancetopics", .andExpect(jsonPath("$._embedded.qualityassurancetopics",

View File

@@ -40,7 +40,7 @@ qaevents.openaire.pid-href-prefix.ncid = https://ci.nii.ac.jp/ncid/
qaevents.openaire.broker-url = http://api.openaire.eu/broker qaevents.openaire.broker-url = http://api.openaire.eu/broker
###### QAEvent source Configuration ###### ###### QAEvent source Configuration ######
qaevents.sources = OpenAIRE, DSpaceUsers qaevents.sources = openaire, DSpaceUsers, coar-notify
### Withdrawal&Reinstate correction Group ### ### Withdrawal&Reinstate correction Group ###
# Members of this group enabled to make requests for the Withdrawn or Reinstate of an item. # Members of this group enabled to make requests for the Withdrawn or Reinstate of an item.

View File

@@ -104,17 +104,6 @@
</property> </property>
</bean> </bean>
<bean id="org.dspace.qaevent.service.QAEventSecurityService" class="org.dspace.qaevent.service.impl.QAEventSecurityServiceImpl">
<property name="defaultSecurity">
<bean class="org.dspace.qaevent.security.AdministratorsOnlyQASecurity" />
</property>
<property name="qaSecurityConfiguration">
<map>
<entry key="coar-notify" value-ref="submitterQASecurity" />
</map>
</property>
</bean>
<bean id="submitterQASecurity" class="org.dspace.qaevent.security.UserBasedFilterQASecurity"> <bean id="submitterQASecurity" class="org.dspace.qaevent.security.UserBasedFilterQASecurity">
<property name="filterTemplate"> <property name="filterTemplate">
<!-- we need to escape the { as it as a special meaning for the message format --> <!-- we need to escape the { as it as a special meaning for the message format -->