Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mongo DB Storage #89

Merged
merged 16 commits into from
Jul 22, 2024
6 changes: 3 additions & 3 deletions .github/workflows/.trivyignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# April 17
# Spring boot needs to update its version of spring
CVE-2024-22262
# July 17
# Spring boot needs to update its version of Apache Tomcat
CVE-2024-34750
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
target/
.idea
src/main/resources/*
src/main/resources/application.properties
.mvn/
31 changes: 16 additions & 15 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<relativePath/>
<version>3.2.4</version> <!-- lookup parent from repository -->
<version>3.3.1</version> <!-- lookup parent from repository -->
</parent>
<artifactId>handle-manager</artifactId>
<version>0.0.1-SNAPSHOT</version>
Expand All @@ -18,17 +18,17 @@
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<testcontainers.version>1.17.6</testcontainers.version>
<testcontainers.version>1.19.8</testcontainers.version>
<apache-commons.version>4.3</apache-commons.version>
<mockito-inline.version>5.2.0</mockito-inline.version>
<mongodb-driver.version>5.1.1</mongodb-driver.version>
<okhttp3.version>4.10.0</okhttp3.version>
<version.victools>4.35.0</version.victools>
<sonar.coverage.jacoco.xmlReportPaths>
../app-it/target/site/jacoco-aggregate/jacoco.xml
</sonar.coverage.jacoco.xmlReportPaths>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.organization>dissco</sonar.organization>
<spring-security.version>6.2.3</spring-security.version> <!-- 21/03/24: CVE-2024-22257-->
<version.victools>4.28.0</version.victools>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -97,21 +97,17 @@

<!--Database Dependencies -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>${mongodb-driver.version}</version>
</dependency>

<!--JsonSchema -->
Expand Down Expand Up @@ -177,6 +173,11 @@
<groupId>org.springframework.boot</groupId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mongodb</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package eu.dissco.core.handlemanager.configuration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.time.Instant;
import java.util.Random;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
Expand All @@ -13,6 +15,8 @@
@Configuration
public class AppConfig {

public static final String DATE_STRING = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

@Bean
public DocumentBuilderFactory documentBuilderFactory() throws ParserConfigurationException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Expand All @@ -31,7 +35,13 @@ public TransformerFactory transformerFactory() throws TransformerConfigurationEx

@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper().findAndRegisterModules();
var mapper = new ObjectMapper()
.findAndRegisterModules();
SimpleModule dateModule = new SimpleModule();
dateModule.addSerializer(Instant.class, new InstantSerializer());
dateModule.addDeserializer(Instant.class, new InstantDeserializer());
mapper.registerModule(dateModule);
return mapper;
}

@Bean
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package eu.dissco.core.handlemanager.configuration;

import static eu.dissco.core.handlemanager.configuration.AppConfig.DATE_STRING;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class InstantDeserializer extends JsonDeserializer<Instant> {

private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_STRING).withZone(
ZoneOffset.UTC);

@Override
public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) {
try {
return Instant.from(formatter.parse(jsonParser.getText()));
} catch (IOException e) {
log.error("An error has occurred deserializing a date. More information: {}", e.getMessage());
return null;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package eu.dissco.core.handlemanager.configuration;

import static eu.dissco.core.handlemanager.configuration.AppConfig.DATE_STRING;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class InstantSerializer extends JsonSerializer<Instant> {

private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_STRING).withZone(
ZoneOffset.UTC);

@Override
public void serialize(Instant value, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) {
try {
jsonGenerator.writeString(formatter.format(value));
} catch (IOException e) {
log.error("An error has occurred serializing a date. More information: {}", e.getMessage());
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package eu.dissco.core.handlemanager.configuration;

import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import eu.dissco.core.handlemanager.properties.MongoProperties;
import lombok.RequiredArgsConstructor;
import org.bson.Document;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class MongoConfig {

private final MongoProperties properties;

@Bean
public MongoCollection<Document> getHandleCollection() {
var client = MongoClients.create(properties.getConnectionString());
var database = client.getDatabase(properties.getDatabase());
return database.getCollection("handles");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import com.fasterxml.jackson.databind.JsonNode;
import eu.dissco.core.handlemanager.domain.jsonapi.JsonApiWrapperRead;
import eu.dissco.core.handlemanager.domain.jsonapi.JsonApiWrapperReadSingle;
import eu.dissco.core.handlemanager.domain.jsonapi.JsonApiWrapperWrite;
import eu.dissco.core.handlemanager.domain.requests.RollbackRequest;
import eu.dissco.core.handlemanager.domain.validation.JsonSchemaValidator;
Expand All @@ -18,7 +17,6 @@
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -54,13 +52,13 @@ public class PidController {
// Getters
@Operation(summary = "Resolve single PID record")
@GetMapping("/{prefix}/{suffix}")
public ResponseEntity<JsonApiWrapperReadSingle> resolvePid(@PathVariable("prefix") String prefix,
public ResponseEntity<JsonApiWrapperRead> resolvePid(@PathVariable("prefix") String prefix,
@PathVariable("suffix") String suffix, HttpServletRequest r) throws PidResolutionException {
String path = applicationProperties.getUiUrl() + r.getRequestURI();
String link = applicationProperties.getUiUrl() + "/" + r.getRequestURI();
String handle = prefix + "/" + suffix;

if (prefix.equals(applicationProperties.getPrefix())) {
var node = service.resolveSingleRecord(handle.getBytes(StandardCharsets.UTF_8), path);
var node = service.resolveSingleRecord(handle, link);
return ResponseEntity.status(HttpStatus.OK).body(node);
}
throw new PidResolutionException(
Expand All @@ -73,17 +71,15 @@ public ResponseEntity<JsonApiWrapperReadSingle> resolvePid(@PathVariable("prefix
public ResponseEntity<JsonApiWrapperRead> resolvePids(
@RequestParam List<String> handles,
HttpServletRequest r) throws InvalidRequestException {
String path = applicationProperties.getUiUrl() + r.getRequestURI();
String link = applicationProperties.getUiUrl() + "/" + r.getRequestURI();

if (handles.size() > applicationProperties.getMaxHandles()) {
throw new InvalidRequestException(
"Attempting to resolve more than maximum permitted PIDs in a single request. Maximum handles: "
+ applicationProperties.getMaxHandles());
}
List<byte[]> handleBytes = new ArrayList<>();
handles.forEach(h -> handleBytes.add(h.getBytes(StandardCharsets.UTF_8)));

return ResponseEntity.status(HttpStatus.OK).body(service.resolveBatchRecord(handleBytes, path));
return ResponseEntity.status(HttpStatus.OK).body(service.resolveBatchRecord(handles, link));
}

@Operation(summary = "Given a physical identifier (i.e. local identifier), resolve PID record")
Expand Down Expand Up @@ -124,18 +120,14 @@ public ResponseEntity<JsonApiWrapperWrite> updateRecord(@PathVariable("prefix")
log.info("Received single update request for PID {}/{} from user {}", prefix, suffix,
authentication.getName());
schemaValidator.validatePatchRequest(request);

JsonNode data = request.get(NODE_DATA);
byte[] handle = (prefix + "/" + suffix).getBytes(StandardCharsets.UTF_8);
byte[] handleData = data.get(NODE_ID).asText().getBytes(StandardCharsets.UTF_8);

if (!Arrays.equals(handle, handleData)) {
var handle = (prefix + "/" + suffix);
var handleData = request.get(NODE_DATA).get(NODE_ID).asText();
if (!handle.equals(handleData)) {
throw new InvalidRequestException(String.format(
"Handle in request path does not match id in request body. Path: %s, Body: %s",
new String(handle, StandardCharsets.UTF_8),
new String(handleData, StandardCharsets.UTF_8)));
handle,
handleData));
}

return ResponseEntity.status(HttpStatus.OK).body(service.updateRecords(List.of(request), true));
}

Expand Down Expand Up @@ -171,7 +163,8 @@ public ResponseEntity<JsonApiWrapperWrite> archiveRecord(@PathVariable("prefix")
+ new String(handle, StandardCharsets.UTF_8)
+ ". Body: " + new String(handleRequest, StandardCharsets.UTF_8));
}
return ResponseEntity.status(HttpStatus.OK).body(service.archiveRecordBatch(List.of(request)));
return ResponseEntity.status(HttpStatus.OK)
.body(service.tombstoneRecords(List.of(request)));
}

@Operation(summary = "rollback handle creation")
Expand Down Expand Up @@ -227,7 +220,7 @@ public ResponseEntity<JsonApiWrapperWrite> archiveRecords(@RequestBody List<Json
schemaValidator.validatePutRequest(request);
}
log.info("Received valid archive request");
return ResponseEntity.status(HttpStatus.OK).body(service.archiveRecordBatch(requests));
return ResponseEntity.status(HttpStatus.OK).body(service.tombstoneRecords(requests));
}

}

This file was deleted.

Loading
Loading