From 1c527f1bd2ec34453c3f95b0e6a58542631c978e Mon Sep 17 00:00:00 2001 From: eskander Date: Thu, 24 Aug 2023 16:55:24 +0300 Subject: [PATCH] [CST-10629] Defined the storage layer of the notify feature --- .../java/org/dspace/app/ldn/LDNMessage.java | 130 ++++++++++++++++++ .../dspace/app/ldn/LDNMessageServiceImpl.java | 81 ++++++++++- .../org/dspace/app/ldn/dao/LDNMessageDao.java | 23 ++++ .../app/ldn/dao/impl/LDNMessageDaoImpl.java | 23 ++++ .../app/ldn/service/LDNMessageService.java | 42 +++++- .../org/dspace/core/AbstractHibernateDAO.java | 10 ++ .../main/java/org/dspace/core/GenericDAO.java | 11 ++ .../V8.0_2023.08.23__LDN_Messages_table.sql | 28 ++++ .../V8.0_2023.08.23__LDN_Messages_table.sql | 28 ++++ .../dspace/app/rest/LDNInboxController.java | 43 +++--- .../DSpaceApiExceptionControllerAdvice.java | 2 +- .../exception/InvalidLDNMessageException.java | 26 ++++ .../dspace/app/rest/LDNInboxControllerIT.java | 76 +++++++++- dspace/config/hibernate.cfg.xml | 2 + .../config/spring/api/core-dao-services.xml | 1 + 15 files changed, 499 insertions(+), 27 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/app/ldn/LDNMessage.java create mode 100644 dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java create mode 100644 dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V8.0_2023.08.23__LDN_Messages_table.sql create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V8.0_2023.08.23__LDN_Messages_table.sql create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/InvalidLDNMessageException.java diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessage.java b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessage.java new file mode 100644 index 0000000000..eaec35db76 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessage.java @@ -0,0 +1,130 @@ +/** + * 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.ldn; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.dspace.content.DSpaceObject; +import org.dspace.core.ReloadableEntity; + +/** + * Class representing ldnMessages stored in the DSpace system. + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + */ +@Entity +@Table(name = "ldn_messages") +public class LDNMessage implements ReloadableEntity { + + @Id + private String id; + + @ManyToOne + @JoinColumn(name = "object", referencedColumnName = "uuid") + private DSpaceObject object; + + @Column(name = "message", nullable = false, columnDefinition = "text") + private String message; + + @Column(name = "type") + private String type; + + @ManyToOne + @JoinColumn(name = "origin", referencedColumnName = "id") + private NotifyServiceEntity origin; + + @ManyToOne + @JoinColumn(name = "target", referencedColumnName = "id") + private NotifyServiceEntity target; + + @ManyToOne + @JoinColumn(name = "inReplyTo", referencedColumnName = "id") + private LDNMessage inReplyTo; + + @ManyToOne + @JoinColumn(name = "context", referencedColumnName = "uuid") + private DSpaceObject context; + + protected LDNMessage() { + + } + + protected LDNMessage(String id) { + this.id = id; + } + + @Override + public String getID() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public DSpaceObject getObject() { + return object; + } + + public void setObject(DSpaceObject object) { + this.object = object; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public NotifyServiceEntity getOrigin() { + return origin; + } + + public void setOrigin(NotifyServiceEntity origin) { + this.origin = origin; + } + + public NotifyServiceEntity getTarget() { + return target; + } + + public void setTarget(NotifyServiceEntity target) { + this.target = target; + } + + public LDNMessage getInReplyTo() { + return inReplyTo; + } + + public void setInReplyTo(LDNMessage inReplyTo) { + this.inReplyTo = inReplyTo; + } + + public DSpaceObject getContext() { + return context; + } + + public void setContext(DSpaceObject context) { + this.context = context; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageServiceImpl.java index d710b4c26b..c69dc9f86c 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageServiceImpl.java @@ -8,24 +8,101 @@ package org.dspace.app.ldn; import java.sql.SQLException; +import java.util.UUID; +import com.google.gson.Gson; +import org.apache.commons.lang3.StringUtils; +import org.dspace.app.ldn.dao.LDNMessageDao; +import org.dspace.app.ldn.model.Notification; +import org.dspace.app.ldn.model.Service; import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.app.ldn.service.NotifyService; +import org.dspace.content.DSpaceObject; +import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.handle.service.HandleService; +import org.dspace.services.ConfigurationService; +import org.springframework.beans.factory.annotation.Autowired; /** * Implementation of {@link LDNMessageService} * - * @author Mohamed Eskander (mohamed.eskander at 4science.com) + * @author Mohamed Eskander (mohamed.eskander at 4science dot it) */ public class LDNMessageServiceImpl implements LDNMessageService { + @Autowired(required = true) + private LDNMessageDao ldnMessageDao; + @Autowired(required = true) + private NotifyService notifyService; + @Autowired(required = true) + private ConfigurationService configurationService; + @Autowired(required = true) + private HandleService handleService; + @Autowired(required = true) + private ItemService itemService; + protected LDNMessageServiceImpl() { } @Override - public void create(Context context, String id) throws SQLException { + public LDNMessage find(Context context, String id) throws SQLException { + return ldnMessageDao.findByID(context, LDNMessage.class, id); + } + @Override + public LDNMessage create(Context context, String id) throws SQLException { + return ldnMessageDao.create(context, new LDNMessage(id)); + } + + @Override + public LDNMessage create(Context context, Notification notification) throws SQLException { + LDNMessage ldnMessage = create(context, notification.getId()); + + ldnMessage.setObject(findDspaceObjectByUrl(context, notification.getId())); + + if (null != notification.getContext()) { + ldnMessage.setContext(findDspaceObjectByUrl(context, notification.getContext().getId())); + } + + ldnMessage.setOrigin(findNotifyService(context, notification.getOrigin())); + ldnMessage.setTarget(findNotifyService(context, notification.getTarget())); + ldnMessage.setInReplyTo(find(context, notification.getInReplyTo())); + ldnMessage.setMessage(new Gson().toJson(notification)); + ldnMessage.setType(StringUtils.joinWith(",", notification.getType())); + + update(context, ldnMessage); + return ldnMessage; + } + + @Override + public void update(Context context, LDNMessage ldnMessage) throws SQLException { + ldnMessageDao.save(context, ldnMessage); + } + + private DSpaceObject findDspaceObjectByUrl(Context context, String url) throws SQLException { + String dspaceUrl = configurationService.getProperty("dspace.ui.url") + "/handle/"; + + if (url.startsWith(dspaceUrl)) { + return handleService.resolveToObject(context, url.substring(dspaceUrl.length())); + } + + String handleResolver = configurationService.getProperty("handle.canonical.prefix", "https://hdl.handle.net/"); + if (url.startsWith(handleResolver)) { + return handleService.resolveToObject(context, url.substring(handleResolver.length())); + } + + dspaceUrl = configurationService.getProperty("dspace.ui.url") + "/items/"; + if (url.startsWith(dspaceUrl)) { + return itemService.find(context, UUID.fromString(url.substring(dspaceUrl.length()))); + } + + return null; + } + + private NotifyServiceEntity findNotifyService(Context context, Service service) throws SQLException { + return notifyService.findByLdnUrl(context, service.getInbox()); } } diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java new file mode 100644 index 0000000000..05a46eb502 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java @@ -0,0 +1,23 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.ldn.dao; + +import org.dspace.app.ldn.LDNMessage; +import org.dspace.core.GenericDAO; + +/** + * Database Access Object interface class for the LDNMessage object. + * + * The implementation of this class is responsible for all database calls for the LDNMessage object + * and is autowired by spring + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + */ +public interface LDNMessageDao extends GenericDAO { + +} diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java new file mode 100644 index 0000000000..5456c9e988 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java @@ -0,0 +1,23 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.ldn.dao.impl; + +import org.dspace.app.ldn.LDNMessage; +import org.dspace.app.ldn.dao.LDNMessageDao; +import org.dspace.core.AbstractHibernateDAO; + +/** + * Hibernate implementation of the Database Access Object interface class for the LDNMessage object. + * This class is responsible for all database calls for the LDNMessage object + * and is autowired by spring + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + */ +public class LDNMessageDaoImpl extends AbstractHibernateDAO implements LDNMessageDao { + +} diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java b/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java index 10da8c40f1..70808ed5c6 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java @@ -9,15 +9,53 @@ package org.dspace.app.ldn.service; import java.sql.SQLException; +import org.dspace.app.ldn.LDNMessage; +import org.dspace.app.ldn.model.Notification; import org.dspace.core.Context; /** * Service interface class for the {@link LDNMessage} object. * - * @author Mohamed Eskander (mohamed.eskander at 4science.com) + * @author Mohamed Eskander (mohamed.eskander at 4science dot it) */ public interface LDNMessageService { - public void create(Context context, String id) throws SQLException; + /** + * find the ldn message by id + * + * @param context the context + * @param id the uri + * @return the ldn message by id + * @throws SQLException If something goes wrong in the database + */ + public LDNMessage find(Context context, String id) throws SQLException; + /** + * Creates a new LDNMessage + * + * @param context The DSpace context + * @param id the uri + * @return the created LDN Message + * @throws SQLException If something goes wrong in the database + */ + public LDNMessage create(Context context, String id) throws SQLException; + + /** + * Creates a new LDNMessage + * + * @param context The DSpace context + * @param notification the requested notification + * @return the created LDN Message + * @throws SQLException If something goes wrong in the database + */ + public LDNMessage create(Context context, Notification notification) throws SQLException; + + /** + * Update the provided LDNMessage + * + * @param context The DSpace context + * @param ldnMessage the LDNMessage + * @throws SQLException If something goes wrong in the database + */ + public void update(Context context, LDNMessage ldnMessage) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java index 32ad747d76..38923658f0 100644 --- a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java +++ b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java @@ -102,6 +102,16 @@ public abstract class AbstractHibernateDAO implements GenericDAO { return result; } + @Override + public T findByID(Context context, Class clazz, String id) throws SQLException { + if (id == null) { + return null; + } + @SuppressWarnings("unchecked") + T result = (T) getHibernateSession(context).get(clazz, id); + return result; + } + @Override public List findMany(Context context, String query) throws SQLException { @SuppressWarnings("unchecked") diff --git a/dspace-api/src/main/java/org/dspace/core/GenericDAO.java b/dspace-api/src/main/java/org/dspace/core/GenericDAO.java index a04a0ccbdc..9835e18ad3 100644 --- a/dspace-api/src/main/java/org/dspace/core/GenericDAO.java +++ b/dspace-api/src/main/java/org/dspace/core/GenericDAO.java @@ -102,6 +102,17 @@ public interface GenericDAO { */ public T findByID(Context context, Class clazz, UUID id) throws SQLException; + /** + * Fetch the entity identified by its String primary key. + * + * @param context current DSpace context. + * @param clazz class of entity to be found. + * @param id primary key of the database record. + * @return the found entity. + * @throws SQLException + */ + public T findByID(Context context, Class clazz, String id) throws SQLException; + /** * Execute a JPQL query and return a collection of results. * diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V8.0_2023.08.23__LDN_Messages_table.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V8.0_2023.08.23__LDN_Messages_table.sql new file mode 100644 index 0000000000..958e72cadd --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V8.0_2023.08.23__LDN_Messages_table.sql @@ -0,0 +1,28 @@ +-- +-- 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/ +-- + +------------------------------------------------------------------------------- +-- Table to store LDN messages +------------------------------------------------------------------------------- + +CREATE TABLE ldn_messages +( + id VARCHAR(255) PRIMARY KEY, + object uuid, + message TEXT, + type VARCHAR(255), + origin INTEGER, + target INTEGER, + inReplyTo VARCHAR(255), + context uuid, + FOREIGN KEY (object) REFERENCES dspaceobject (uuid) ON DELETE SET NULL, + FOREIGN KEY (context) REFERENCES dspaceobject (uuid) ON DELETE SET NULL, + FOREIGN KEY (origin) REFERENCES notifyservices (id) ON DELETE SET NULL, + FOREIGN KEY (target) REFERENCES notifyservices (id) ON DELETE SET NULL, + FOREIGN KEY (inReplyTo) REFERENCES ldn_messages (id) ON DELETE SET NULL +); \ No newline at end of file diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V8.0_2023.08.23__LDN_Messages_table.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V8.0_2023.08.23__LDN_Messages_table.sql new file mode 100644 index 0000000000..958e72cadd --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V8.0_2023.08.23__LDN_Messages_table.sql @@ -0,0 +1,28 @@ +-- +-- 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/ +-- + +------------------------------------------------------------------------------- +-- Table to store LDN messages +------------------------------------------------------------------------------- + +CREATE TABLE ldn_messages +( + id VARCHAR(255) PRIMARY KEY, + object uuid, + message TEXT, + type VARCHAR(255), + origin INTEGER, + target INTEGER, + inReplyTo VARCHAR(255), + context uuid, + FOREIGN KEY (object) REFERENCES dspaceobject (uuid) ON DELETE SET NULL, + FOREIGN KEY (context) REFERENCES dspaceobject (uuid) ON DELETE SET NULL, + FOREIGN KEY (origin) REFERENCES notifyservices (id) ON DELETE SET NULL, + FOREIGN KEY (target) REFERENCES notifyservices (id) ON DELETE SET NULL, + FOREIGN KEY (inReplyTo) REFERENCES ldn_messages (id) ON DELETE SET NULL +); \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java index 178eab5df5..59ad02c9de 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java @@ -7,17 +7,17 @@ */ package org.dspace.app.rest; -import java.net.URI; +import java.util.regex.Pattern; +import org.apache.commons.validator.routines.UrlValidator; import org.apache.logging.log4j.Logger; -import org.dspace.app.ldn.LDNRouter; import org.dspace.app.ldn.model.Notification; import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.app.rest.exception.InvalidLDNMessageException; import org.dspace.core.Context; import org.dspace.web.ContextUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -35,10 +35,6 @@ public class LDNInboxController { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(); - @Lazy - @Autowired - private LDNRouter router; - @Autowired private LDNMessageService ldnMessageService; @@ -46,24 +42,19 @@ public class LDNInboxController { * LDN DSpace inbox. * * @param notification received notification - * @return ResponseEntity 400 not stored, 201 stored + * @return ResponseEntity 400 not stored, 202 stored * @throws Exception */ @PostMapping(value = "/inbox", consumes = "application/ld+json") public ResponseEntity inbox(@RequestBody Notification notification) throws Exception { Context context = ContextUtil.obtainCurrentRequestContext(); - - ldnMessageService.create(context, notification.getId()); - - log.info("stored notification {} {}", - notification.getId(), - notification.getType()); - - URI target = new URI(notification.getTarget().getInbox()); - - return ResponseEntity.created(target) + validate(notification); + ldnMessageService.create(context, notification); + log.info("stored notification {} {}", notification.getId(), notification.getType()); + context.commit(); + return ResponseEntity.accepted() .body(String.format("Successfully stored notification %s %s", - notification.getId(), notification.getType())); + notification.getId(), notification.getType())); } /** @@ -89,4 +80,18 @@ public class LDNInboxController { .body(e.getMessage()); } + private void validate(Notification notification) { + String id = notification.getId(); + Pattern URNRegex = + Pattern.compile("^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); + + if (!URNRegex.matcher(id).matches() && !new UrlValidator().isValid(id)) { + throw new InvalidLDNMessageException("Invalid URI format for 'id' field."); + } + + if (notification.getOrigin() == null || notification.getTarget() == null || notification.getObject() == null) { + throw new InvalidLDNMessageException("Origin or Target or Object is missing"); + } + } + } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java index 4ad1e47934..90d9b98786 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java @@ -92,7 +92,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH HttpServletResponse.SC_FORBIDDEN); } - @ExceptionHandler({IllegalArgumentException.class, MultipartException.class}) + @ExceptionHandler({IllegalArgumentException.class, MultipartException.class, InvalidLDNMessageException.class}) protected void handleWrongRequestException(HttpServletRequest request, HttpServletResponse response, Exception ex) throws IOException { sendErrorResponse(request, response, ex, "Request is invalid or incorrect", HttpServletResponse.SC_BAD_REQUEST); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/InvalidLDNMessageException.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/InvalidLDNMessageException.java new file mode 100644 index 0000000000..0542ef02cd --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/InvalidLDNMessageException.java @@ -0,0 +1,26 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.exception; + + +/** + * This exception is thrown when the given LDN Message json is invalid + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + */ +public class InvalidLDNMessageException extends RuntimeException { + + public InvalidLDNMessageException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidLDNMessageException(String message) { + super(message); + } + +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java index d99737bcc6..4844fb9100 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java @@ -11,12 +11,32 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +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.services.ConfigurationService; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { + @Autowired + private ConfigurationService configurationService; + @Test public void ldnInboxEndorsementActionTest() throws Exception { + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context).withName("community").build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + Item item = ItemBuilder.createItem(context, collection).build(); + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + + context.restoreAuthSystemState(); + String message = "{\n" + " \"@context\": [\n" + " \"https://www.w3.org/ns/activitystreams\",\n" + @@ -29,7 +49,7 @@ public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { " },\n" + " \"id\": \"urn:uuid:0370c0fb-bb78-4a9b-87f5-bed307a509dd\",\n" + " \"object\": {\n" + - " \"id\": \"https://research-organisation.org/repository/preprint/201203/421/\",\n" + + " \"id\": \"" + object + "\",\n" + " \"ietf:cite-as\": \"https://doi.org/10.5555/12345680\",\n" + " \"type\": \"sorg:AboutPage\",\n" + " \"url\": {\n" + @@ -61,7 +81,7 @@ public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { .perform(post("/ldn/inbox") .contentType("application/ld+json") .content(message)) - .andExpect(status().isCreated()); + .andExpect(status().isAccepted()); } @Test @@ -119,7 +139,57 @@ public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { .perform(post("/ldn/inbox") .contentType("application/ld+json") .content(message)) - .andExpect(status().isCreated()); + .andExpect(status().isAccepted()); + } + + @Test + public void ldnInboxEndorsementActionBadRequestTest() throws Exception { + // id is not an uri + String message = "{\n" + + " \"@context\": [\n" + + " \"https://www.w3.org/ns/activitystreams\",\n" + + " \"https://purl.org/coar/notify\"\n" + + " ],\n" + + " \"actor\": {\n" + + " \"id\": \"https://orcid.org/0000-0002-1825-0097\",\n" + + " \"name\": \"Josiah Carberry\",\n" + + " \"type\": \"Person\"\n" + + " },\n" + + " \"id\": \"123456789\",\n" + + " \"object\": {\n" + + " \"id\": \"https://overlay-journal.com/articles/00001/\",\n" + + " \"ietf:cite-as\": \"https://doi.org/10.5555/12345680\",\n" + + " \"type\": \"sorg:AboutPage\",\n" + + " \"url\": {\n" + + " \"id\": \"https://research-organisation.org/repository/preprint/201203/421/content.pdf\",\n" + + " \"mediaType\": \"application/pdf\",\n" + + " \"type\": [\n" + + " \"Article\",\n" + + " \"sorg:ScholarlyArticle\"\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"origin\": {\n" + + " \"id\": \"https://research-organisation.org/repository\",\n" + + " \"inbox\": \"https://research-organisation.org/inbox/\",\n" + + " \"type\": \"Service\"\n" + + " },\n" + + " \"target\": {\n" + + " \"id\": \"https://overlay-journal.com/system\",\n" + + " \"inbox\": \"https://overlay-journal.com/inbox/\",\n" + + " \"type\": \"Service\"\n" + + " },\n" + + " \"type\": [\n" + + " \"Offer\",\n" + + " \"coar-notify:EndorsementAction\"\n" + + " ]\n" + + "}"; + + getClient(getAuthToken(admin.getEmail(), password)) + .perform(post("/ldn/inbox") + .contentType("application/ld+json") + .content(message)) + .andExpect(status().isBadRequest()); } } diff --git a/dspace/config/hibernate.cfg.xml b/dspace/config/hibernate.cfg.xml index 4fa9b393d4..afea4dbba2 100644 --- a/dspace/config/hibernate.cfg.xml +++ b/dspace/config/hibernate.cfg.xml @@ -100,5 +100,7 @@ + + diff --git a/dspace/config/spring/api/core-dao-services.xml b/dspace/config/spring/api/core-dao-services.xml index be8b672355..5d954d5e57 100644 --- a/dspace/config/spring/api/core-dao-services.xml +++ b/dspace/config/spring/api/core-dao-services.xml @@ -72,5 +72,6 @@ +