Skip to content

Commit

Permalink
Merged in coar-notify-7_CST-13257 (pull request DSpace#1550)
Browse files Browse the repository at this point in the history
[CST-13257] added lowerIp and upperIp fields and operations to NotifyServiceEntity

Approved-by: Stefano Maffei
  • Loading branch information
eskander17 authored and steph-ieffam committed Jan 17, 2024
2 parents 4116a27 + 0191d91 commit a72a370
Show file tree
Hide file tree
Showing 20 changed files with 643 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ public class LDNMessageEntity implements ReloadableEntity<String> {
* LDN messages interact with a fictitious queue. Scheduled tasks manage the queue.
*/

/**
/**
* Message must not be processed.
*/
public static final Integer QUEUE_STATUS_UNTRUSTED_IP = 0;

/**
* Message queued, it has to be elaborated.
*/
public static final Integer QUEUE_STATUS_QUEUED = 1;
Expand Down Expand Up @@ -113,6 +118,9 @@ public class LDNMessageEntity implements ReloadableEntity<String> {
@Column(name = "coar_notify_type")
private String coarNotifyType;

@Column(name = "source_ip")
private String sourceIp;

protected LDNMessageEntity() {

}
Expand Down Expand Up @@ -255,6 +263,14 @@ public void setQueueTimeout(Date queueTimeout) {
this.queueTimeout = queueTimeout;
}

public String getSourceIp() {
return sourceIp;
}

public void setSourceIp(String sourceIp) {
this.sourceIp = sourceIp;
}

@Override
public String toString() {
return "LDNMessage id:" + this.getID() + " typed:" + this.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ public class NotifyServiceEntity implements ReloadableEntity<Integer> {
@Column(name = "score")
private BigDecimal score;

@Column(name = "lower_ip")
private String lowerIp;

@Column(name = "upper_ip")
private String upperIp;

public void setId(Integer id) {
this.id = id;
}
Expand Down Expand Up @@ -130,4 +136,21 @@ public BigDecimal getScore() {
public void setScore(BigDecimal score) {
this.score = score;
}

public String getLowerIp() {
return lowerIp;
}

public void setLowerIp(String lowerIp) {
this.lowerIp = lowerIp;
}

public String getUpperIp() {
return upperIp;
}

public void setUpperIp(String upperIp) {
this.upperIp = upperIp;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ public interface LDNMessageService {
*
* @param context The DSpace context
* @param notification the requested notification
* @param sourceIp the source ip
* @return the created LDN Message
* @throws SQLException If something goes wrong in the database
*/
public LDNMessageEntity create(Context context, Notification notification) throws SQLException;
public LDNMessageEntity create(Context context, Notification notification, String sourceIp) throws SQLException;

/**
* Update the provided LDNMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/
package org.dspace.app.ldn.service.impl;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -85,7 +87,7 @@ public LDNMessageEntity create(Context context, String id) throws SQLException {
}

@Override
public LDNMessageEntity create(Context context, Notification notification) throws SQLException {
public LDNMessageEntity create(Context context, Notification notification, String sourceIp) throws SQLException {
LDNMessageEntity ldnMessage = create(context, notification.getId());
ldnMessage.setObject(findDspaceObjectByUrl(context, notification.getObject().getId()));
if (null != notification.getContext()) {
Expand Down Expand Up @@ -124,11 +126,55 @@ public LDNMessageEntity create(Context context, Notification notification) throw
ldnMessage.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_UNTRUSTED);
}
ldnMessage.setQueueTimeout(new Date());
ldnMessage.setSourceIp(sourceIp);

if (!isValidIp(ldnMessage)) {
ldnMessage.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_UNTRUSTED_IP);
}

update(context, ldnMessage);
return ldnMessage;
}

private boolean isValidIp(LDNMessageEntity message) {

boolean enabled = configurationService.getBooleanProperty("coar-notify.ip-range.enabled", true);

if (!enabled) {
return true;
}

NotifyServiceEntity notifyService =
message.getOrigin() == null ? message.getTarget() : message.getOrigin();

String lowerIp = notifyService.getLowerIp();
String upperIp = notifyService.getUpperIp();

try {
InetAddress ip = InetAddress.getByName(message.getSourceIp());
InetAddress lowerBoundAddress = InetAddress.getByName(lowerIp);
InetAddress upperBoundAddress = InetAddress.getByName(upperIp);

long ipLong = ipToLong(ip);
long lowerBoundLong = ipToLong(lowerBoundAddress);
long upperBoundLong = ipToLong(upperBoundAddress);

return ipLong >= lowerBoundLong && ipLong <= upperBoundLong;
} catch (UnknownHostException e) {
return false;
}
}

private long ipToLong(InetAddress ip) {
byte[] octets = ip.getAddress();
long result = 0;
for (byte octet : octets) {
result <<= 8;
result |= octet & 0xff;
}
return result;
}

@Override
public void update(Context context, LDNMessageEntity ldnMessage) throws SQLException {
//CST-12126 then LDNMessageService.update() when the origin is set != null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--
-- 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/
--

--------------------------------------------------------------------------
-- ADD IP Range columns to notifyservice table
--------------------------------------------------------------------------

ALTER TABLE notifyservice ADD COLUMN lower_ip VARCHAR(45);

ALTER TABLE notifyservice ADD COLUMN upper_ip VARCHAR(45);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--
-- 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/
--

--------------------------------------------------------------------------
-- ADD source_ip columns to ldn_message table
--------------------------------------------------------------------------

ALTER TABLE ldn_message ADD COLUMN source_ip VARCHAR(45);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--
-- 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/
--

--------------------------------------------------------------------------
-- ADD IP Range columns to notifyservice table
--------------------------------------------------------------------------

ALTER TABLE notifyservice ADD COLUMN lower_ip VARCHAR(45);

ALTER TABLE notifyservice ADD COLUMN upper_ip VARCHAR(45);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--
-- 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/
--

--------------------------------------------------------------------------
-- ADD source_ip columns to ldn_message table
--------------------------------------------------------------------------

ALTER TABLE ldn_message ADD COLUMN source_ip VARCHAR(45);
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,14 @@ public NotifyServiceBuilder isEnabled(boolean enabled) {
return this;
}

public NotifyServiceBuilder withLowerIp(String lowerIp) {
notifyServiceEntity.setLowerIp(lowerIp);
return this;
}

public NotifyServiceBuilder withUpperIp(String upperIp) {
notifyServiceEntity.setUpperIp(upperIp);
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package org.dspace.app.rest;

import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.validator.routines.UrlValidator;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -51,12 +52,14 @@ public class LDNInboxController {
* @throws Exception
*/
@PostMapping(value = "/inbox", consumes = "application/ld+json")
public ResponseEntity<Object> inbox(@RequestBody Notification notification) throws Exception {
public ResponseEntity<Object> inbox(HttpServletRequest request, @RequestBody Notification notification)
throws Exception {

Context context = ContextUtil.obtainCurrentRequestContext();
validate(notification);
log.info("stored notification {} {}", notification.getId(), notification.getType());

LDNMessageEntity ldnMsgEntity = ldnMessageService.create(context, notification);
LDNMessageEntity ldnMsgEntity = ldnMessageService.create(context, notification, request.getRemoteAddr());
log.info("stored ldn message {}", ldnMsgEntity);
context.commit();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public NotifyServiceRest convert(NotifyServiceEntity obj, Projection projection)
notifyServiceRest.setLdnUrl(obj.getLdnUrl());
notifyServiceRest.setEnabled(obj.isEnabled());
notifyServiceRest.setScore(obj.getScore());
notifyServiceRest.setLowerIp(obj.getLowerIp());
notifyServiceRest.setUpperIp(obj.getUpperIp());

if (obj.getInboundPatterns() != null) {
notifyServiceRest.setNotifyServiceInboundPatterns(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class NotifyServiceRest extends BaseObjectRest<Integer> {
private String ldnUrl;
private boolean enabled;
private BigDecimal score;
private String lowerIp;
private String upperIp;

private List<NotifyServiceInboundPatternRest> notifyServiceInboundPatterns;

Expand Down Expand Up @@ -103,4 +105,20 @@ public void setScore(BigDecimal score) {
this.score = score;
}

public String getLowerIp() {
return lowerIp;
}

public void setLowerIp(String lowerIp) {
this.lowerIp = lowerIp;
}

public String getUpperIp() {
return upperIp;
}

public void setUpperIp(String upperIp) {
this.upperIp = upperIp;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ protected NotifyServiceRest createAndReturn(Context context) throws AuthorizeExc
notifyServiceEntity.setUrl(notifyServiceRest.getUrl());
notifyServiceEntity.setLdnUrl(notifyServiceRest.getLdnUrl());
notifyServiceEntity.setEnabled(notifyServiceRest.isEnabled());
notifyServiceEntity.setLowerIp(notifyServiceRest.getLowerIp());
notifyServiceEntity.setUpperIp(notifyServiceRest.getUpperIp());

if (notifyServiceRest.getNotifyServiceInboundPatterns() != null) {
appendNotifyServiceInboundPatterns(context, notifyServiceEntity,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository.patch.operation.ldn;

import java.sql.SQLException;

import org.dspace.app.ldn.NotifyServiceEntity;
import org.dspace.app.ldn.service.NotifyService;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* Implementation for NotifyService lowerIp Replace patches.
*
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/ldn/ldnservices/<:id-notifyService> -H "
* Content-Type: application/json" -d '
* [{
* "op": "replace",
* "path": "/lowerIp",
* "value": "lowerIp value"
* }]'
* </code>
*/
@Component
public class NotifyServiceLowerIpReplaceOperation extends PatchOperation<NotifyServiceEntity> {

@Autowired
private NotifyService notifyService;

private static final String OPERATION_PATH = "/lowerip";

@Override
public NotifyServiceEntity perform(Context context, NotifyServiceEntity notifyServiceEntity, Operation operation)
throws SQLException {
checkOperationValue(operation.getValue());

Object lowerIp = operation.getValue();
if (lowerIp == null | !(lowerIp instanceof String)) {
throw new UnprocessableEntityException("The /lowerIp value must be a string");
}

checkModelForExistingValue(notifyServiceEntity);
notifyServiceEntity.setLowerIp((String) lowerIp);
notifyService.update(context, notifyServiceEntity);
return notifyServiceEntity;
}

/**
* Checks whether the lowerIp of notifyServiceEntity has an existing value to replace
* @param notifyServiceEntity Object on which patch is being done
*/
private void checkModelForExistingValue(NotifyServiceEntity notifyServiceEntity) {
if (notifyServiceEntity.getLowerIp() == null) {
throw new DSpaceBadRequestException("Attempting to replace a non-existent value (lowerIp).");
}
}

@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof NotifyServiceEntity &&
operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE) &&
operation.getPath().trim().toLowerCase().equalsIgnoreCase(OPERATION_PATH));
}
}
Loading

0 comments on commit a72a370

Please sign in to comment.