[CST-13257] added lowerIp and upperIp fields and operations to NotifyServiceEntity

This commit is contained in:
mohamed eskander
2024-01-12 14:33:27 +02:00
parent 692987df23
commit 1acdde22f1
12 changed files with 495 additions and 2 deletions

View File

@@ -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;
}
@@ -130,4 +136,21 @@ public class NotifyServiceEntity implements ReloadableEntity<Integer> {
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;
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -136,4 +136,14 @@ public class NotifyServiceBuilder extends AbstractBuilder<NotifyServiceEntity, N
return this;
}
public NotifyServiceBuilder withLowerIp(String lowerIp) {
notifyServiceEntity.setLowerIp(lowerIp);
return this;
}
public NotifyServiceBuilder withUpperIp(String upperIp) {
notifyServiceEntity.setUpperIp(upperIp);
return this;
}
}

View File

@@ -37,6 +37,8 @@ public class NotifyServiceConverter implements DSpaceConverter<NotifyServiceEnti
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(

View File

@@ -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;
@@ -103,4 +105,20 @@ public class NotifyServiceRest extends BaseObjectRest<Integer> {
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;
}
}

View File

@@ -112,6 +112,8 @@ public class NotifyServiceRestRepository extends DSpaceRestRepository<NotifyServ
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,

View File

@@ -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));
}
}

View File

@@ -0,0 +1,47 @@
/**
* 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.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.stereotype.Component;
/**
* Implementation for NotifyService LowerIp Or UpperIp Remove patches.
*
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/ldn/ldnservices/<:id-notifyService> -H "
* Content-Type: application/json" -d '
* [{
* "op": "remove",
* "path": "/lowerIp"
* }]'
* </code>
*/
@Component
public class NotifyServiceLowerOrUpperRemoveOperation extends PatchOperation<NotifyServiceEntity> {
@Override
public NotifyServiceEntity perform(Context context, NotifyServiceEntity notifyServiceEntity, Operation operation)
throws SQLException {
throw new UnprocessableEntityException("/lowerIp or /upperIp are mandatory and can't be removed");
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof NotifyServiceEntity &&
operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE) &&
(operation.getPath().trim().toLowerCase().equalsIgnoreCase("/lowerip") ||
operation.getPath().trim().toLowerCase().equalsIgnoreCase("/upperip")));
}
}

View File

@@ -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 upperIp 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": "/upperIp",
* "value": "upperIp value"
* }]'
* </code>
*/
@Component
public class NotifyServiceUpperIpReplaceOperation extends PatchOperation<NotifyServiceEntity> {
@Autowired
private NotifyService notifyService;
private static final String OPERATION_PATH = "/upperip";
@Override
public NotifyServiceEntity perform(Context context, NotifyServiceEntity notifyServiceEntity, Operation operation)
throws SQLException {
checkOperationValue(operation.getValue());
Object upperIp = operation.getValue();
if (upperIp == null | !(upperIp instanceof String)) {
throw new UnprocessableEntityException("The /upperIp value must be a string");
}
checkModelForExistingValue(notifyServiceEntity);
notifyServiceEntity.setUpperIp((String) upperIp);
notifyService.update(context, notifyServiceEntity);
return notifyServiceEntity;
}
/**
* Checks whether the upperIp of notifyServiceEntity has an existing value to replace
* @param notifyServiceEntity Object on which patch is being done
*/
private void checkModelForExistingValue(NotifyServiceEntity notifyServiceEntity) {
if (notifyServiceEntity.getUpperIp() == null) {
throw new DSpaceBadRequestException("Attempting to replace a non-existent value (upperIp).");
}
}
@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));
}
}

View File

@@ -210,6 +210,8 @@ public class NotifyServiceRestRepositoryIT extends AbstractControllerIntegration
notifyServiceRest.setLdnUrl("https://service.ldn.org/inbox");
notifyServiceRest.setNotifyServiceInboundPatterns(List.of(inboundPatternRestOne, inboundPatternRestTwo));
notifyServiceRest.setEnabled(false);
notifyServiceRest.setLowerIp("192.168.0.1");
notifyServiceRest.setUpperIp("192.168.0.5");
AtomicReference<Integer> idRef = new AtomicReference<Integer>();
String authToken = getAuthToken(admin.getEmail(), password);
@@ -218,7 +220,8 @@ public class NotifyServiceRestRepositoryIT extends AbstractControllerIntegration
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(jsonPath("$", matchNotifyService("service name", "service description",
"https://service.ldn.org/about", "https://service.ldn.org/inbox", false)))
"https://service.ldn.org/about", "https://service.ldn.org/inbox", false,
"192.168.0.1", "192.168.0.5")))
.andDo(result ->
idRef.set((read(result.getResponse().getContentAsString(), "$.id"))));
@@ -228,7 +231,8 @@ public class NotifyServiceRestRepositoryIT extends AbstractControllerIntegration
.andExpect(jsonPath("$.notifyServiceInboundPatterns", hasSize(2)))
.andExpect(jsonPath("$", allOf(
matchNotifyService(idRef.get(), "service name", "service description",
"https://service.ldn.org/about", "https://service.ldn.org/inbox", false),
"https://service.ldn.org/about", "https://service.ldn.org/inbox", false,
"192.168.0.1", "192.168.0.5"),
hasJsonPath("$.notifyServiceInboundPatterns", containsInAnyOrder(
matchNotifyServicePattern("patternA", "itemFilterA", true),
matchNotifyServicePattern("patternB", null, false)
@@ -2304,4 +2308,185 @@ public class NotifyServiceRestRepositoryIT extends AbstractControllerIntegration
super.destroy();
}
@Test
public void notifyServiceLowerIpReplaceOperationBadRequestTest() throws Exception {
context.turnOffAuthorisationSystem();
NotifyServiceEntity notifyServiceEntity =
NotifyServiceBuilder.createNotifyServiceBuilder(context)
.withName("service name")
.withUrl("https://service.ldn.org/about")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation operation = new ReplaceOperation("/lowerIp", "192.168.0.1");
ops.add(operation);
String patchBody = getPatchContent(ops);
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken)
.perform(patch("/api/ldn/ldnservices/" + notifyServiceEntity.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isBadRequest());
}
@Test
public void notifyServiceLowerIpReplaceOperationTest() throws Exception {
context.turnOffAuthorisationSystem();
NotifyServiceEntity notifyServiceEntity =
NotifyServiceBuilder.createNotifyServiceBuilder(context)
.withName("service name")
.withDescription("service description")
.withUrl("https://service.ldn.org/about")
.withLdnUrl("https://service.ldn.org/inbox")
.withLowerIp("192.168.0.1")
.withUpperIp("192.168.0.5")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation operation = new ReplaceOperation("/lowerIp", "192.168.0.2");
ops.add(operation);
String patchBody = getPatchContent(ops);
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken)
.perform(patch("/api/ldn/ldnservices/" + notifyServiceEntity.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", matchNotifyService(notifyServiceEntity.getID(), "service name",
"service description", "https://service.ldn.org/about", "https://service.ldn.org/inbox",
false, "192.168.0.2", "192.168.0.5"))
);
}
@Test
public void notifyServiceLowerIpRemoveOperationTest() throws Exception {
context.turnOffAuthorisationSystem();
NotifyServiceEntity notifyServiceEntity =
NotifyServiceBuilder.createNotifyServiceBuilder(context)
.withName("service name")
.withDescription("service description")
.withUrl("https://service.ldn.org/about")
.withLdnUrl("https://service.ldn.org/inbox")
.withLowerIp("192.168.0.1")
.withUpperIp("192.168.0.5")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
RemoveOperation operation = new RemoveOperation("/lowerIp");
ops.add(operation);
String patchBody = getPatchContent(ops);
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken)
.perform(patch("/api/ldn/ldnservices/" + notifyServiceEntity.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnprocessableEntity());
}
@Test
public void notifyServiceUpperIpReplaceOperationBadRequestTest() throws Exception {
context.turnOffAuthorisationSystem();
NotifyServiceEntity notifyServiceEntity =
NotifyServiceBuilder.createNotifyServiceBuilder(context)
.withName("service name")
.withUrl("https://service.ldn.org/about")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation operation = new ReplaceOperation("/lowerIp", "192.168.0.8");
ops.add(operation);
String patchBody = getPatchContent(ops);
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken)
.perform(patch("/api/ldn/ldnservices/" + notifyServiceEntity.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isBadRequest());
}
@Test
public void notifyServiceUpperIpReplaceOperationTest() throws Exception {
context.turnOffAuthorisationSystem();
NotifyServiceEntity notifyServiceEntity =
NotifyServiceBuilder.createNotifyServiceBuilder(context)
.withName("service name")
.withDescription("service description")
.withUrl("https://service.ldn.org/about")
.withLdnUrl("https://service.ldn.org/inbox")
.withLowerIp("192.168.0.1")
.withUpperIp("192.168.0.5")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation operation = new ReplaceOperation("/upperIp", "192.168.0.8");
ops.add(operation);
String patchBody = getPatchContent(ops);
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken)
.perform(patch("/api/ldn/ldnservices/" + notifyServiceEntity.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", matchNotifyService(notifyServiceEntity.getID(), "service name",
"service description", "https://service.ldn.org/about", "https://service.ldn.org/inbox",
false, "192.168.0.1", "192.168.0.8"))
);
}
@Test
public void notifyServiceUpperIpRemoveOperationTest() throws Exception {
context.turnOffAuthorisationSystem();
NotifyServiceEntity notifyServiceEntity =
NotifyServiceBuilder.createNotifyServiceBuilder(context)
.withName("service name")
.withDescription("service description")
.withUrl("https://service.ldn.org/about")
.withLdnUrl("https://service.ldn.org/inbox")
.withLowerIp("192.168.0.1")
.withUpperIp("192.168.0.5")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
RemoveOperation operation = new RemoveOperation("/upperIp");
ops.add(operation);
String patchBody = getPatchContent(ops);
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken)
.perform(patch("/api/ldn/ldnservices/" + notifyServiceEntity.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnprocessableEntity());
}
}

View File

@@ -59,6 +59,21 @@ public class NotifyServiceMatcher {
);
}
public static Matcher<? super Object> matchNotifyService(String name, String description, String url,
String ldnUrl, boolean enabled,
String lowerIp, String upperIp) {
return allOf(
hasJsonPath("$.name", is(name)),
hasJsonPath("$.description", is(description)),
hasJsonPath("$.url", is(url)),
hasJsonPath("$.ldnUrl", is(ldnUrl)),
hasJsonPath("$.enabled", is(enabled)),
hasJsonPath("$.lowerIp", is(lowerIp)),
hasJsonPath("$.upperIp", is(upperIp)),
hasJsonPath("$._links.self.href", containsString("/api/ldn/ldnservices/"))
);
}
public static Matcher<? super Object> matchNotifyService(int id, String name, String description,
String url, String ldnUrl) {
return allOf(
@@ -79,6 +94,17 @@ public class NotifyServiceMatcher {
);
}
public static Matcher<? super Object> matchNotifyService(int id, String name, String description,
String url, String ldnUrl, boolean enabled,
String lowerIp, String upperIp) {
return allOf(
hasJsonPath("$.id", is(id)),
matchNotifyService(name, description, url, ldnUrl, enabled, lowerIp, upperIp),
hasJsonPath("$._links.self.href", startsWith(REST_SERVER_URL)),
hasJsonPath("$._links.self.href", endsWith("/api/ldn/ldnservices/" + id))
);
}
public static Matcher<? super Object> matchNotifyServiceWithoutLinks(
int id, String name, String description, String url, String ldnUrl) {
return allOf(