Skip to content

Commit

Permalink
sonar
Browse files Browse the repository at this point in the history
  • Loading branch information
southeo committed Jul 18, 2024
1 parent 729e883 commit d23bf66
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 280 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ public class PidController {
@GetMapping("/{prefix}/{suffix}")
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, path);
var node = service.resolveSingleRecord(handle, link);
return ResponseEntity.status(HttpStatus.OK).body(node);
}
throw new PidResolutionException(
Expand All @@ -71,15 +71,15 @@ public ResponseEntity<JsonApiWrapperRead> resolvePid(@PathVariable("prefix") Str
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());
}

return ResponseEntity.status(HttpStatus.OK).body(service.resolveBatchRecord(handles, 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 @@ -119,7 +119,7 @@ public ResponseEntity<JsonApiWrapperWrite> updateRecord(@PathVariable("prefix")
Authentication authentication) throws InvalidRequestException, UnprocessableEntityException {
log.info("Received single update request for PID {}/{} from user {}", prefix, suffix,
authentication.getName());
schemaValidator.validatePutRequest(request);
schemaValidator.validatePatchRequest(request);
var handle = (prefix + "/" + suffix);
var handleData = request.get(NODE_DATA).get(NODE_ID).asText();
if (!handle.equals(handleData)) {
Expand All @@ -137,7 +137,7 @@ public ResponseEntity<JsonApiWrapperWrite> updateRecords(@RequestBody List<JsonN
Authentication authentication) throws InvalidRequestException, UnprocessableEntityException {
log.info("Validating batch update request from user {}", authentication.getName());
for (JsonNode request : requests) {
schemaValidator.validatePutRequest(request);
schemaValidator.validatePatchRequest(request);
}
log.info("Received valid batch update request for {} PIDS", requests.size());
var result = service.updateRecords(requests, true);
Expand Down Expand Up @@ -192,7 +192,7 @@ public ResponseEntity<JsonApiWrapperWrite> rollbackHandleUpdate(

log.info("Validating rollback update request from user {}", authentication.getName());
for (JsonNode request : requests) {
schemaValidator.validatePutRequest(request);
schemaValidator.validatePatchRequest(request);
}
var handles = requests.stream().map(r -> r.get(NODE_DATA).get(NODE_ID).asText())
.limit(LOG_LIMIT).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ public class FdoAttribute {
int ttl;
Instant timestamp;

public FdoAttribute(FdoProfile fdoAttribute, Instant timestamp, String value) {
public FdoAttribute(FdoProfile fdoAttribute, Instant timestamp, Object value) {
this.index = fdoAttribute.index();
this.type = fdoAttribute.get();
this.timestamp = timestamp;
this.data = new StringHandleData(value);
value = value == null ? "" : value;
this.data = new StringHandleData(value.toString());
this.ttl = 86400;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

import com.fasterxml.jackson.annotation.JsonProperty;

public record PutRequest(@JsonProperty(required = true) PutRequestData data) {
public record PatchRequest(@JsonProperty(required = true) PutRequestData data) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import eu.dissco.core.handlemanager.domain.fdo.FdoType;

public record PostRequestData(
@JsonProperty(required = true)
//@JsonProperty(required = true)
@JsonPropertyDescription("type of object")
FdoType type,
@JsonProperty(required = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.databind.JsonNode;
import eu.dissco.core.handlemanager.domain.fdo.FdoType;

public record PutRequestData(
@JsonProperty(required = true) @JsonPropertyDescription("DiSSCo Identifier of object") String id,
@JsonProperty(required = true) JsonNode attributes) {
@JsonProperty(required = true) JsonNode attributes,
FdoType type) {

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

public record TombstoneRequest(TombstoneRequestData data) {

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

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.databind.JsonNode;

public record TombstoneRequestData(
@JsonProperty(required = true) @JsonPropertyDescription("DiSSCo Identifier of object") String id,
@JsonProperty(required = true) JsonNode attributes
) {

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.dissco.core.handlemanager.domain.validation;

import static eu.dissco.core.handlemanager.domain.fdo.FdoType.TOMBSTONE;
import static eu.dissco.core.handlemanager.domain.jsonapi.JsonApiFields.NODE_ATTRIBUTES;
import static eu.dissco.core.handlemanager.domain.jsonapi.JsonApiFields.NODE_DATA;
import static eu.dissco.core.handlemanager.domain.jsonapi.JsonApiFields.NODE_TYPE;
Expand Down Expand Up @@ -28,8 +29,9 @@
import eu.dissco.core.handlemanager.domain.fdo.OrganisationRequest;
import eu.dissco.core.handlemanager.domain.fdo.SourceSystemRequest;
import eu.dissco.core.handlemanager.domain.fdo.TombstoneRecordRequest;
import eu.dissco.core.handlemanager.domain.requests.PatchRequest;
import eu.dissco.core.handlemanager.domain.requests.PostRequest;
import eu.dissco.core.handlemanager.domain.requests.PutRequest;
import eu.dissco.core.handlemanager.domain.requests.TombstoneRequest;
import eu.dissco.core.handlemanager.exceptions.InvalidRequestException;
import jakarta.validation.constraints.NotEmpty;
import java.util.Arrays;
Expand All @@ -46,31 +48,33 @@ public class JsonSchemaValidator {

// JsonNodes
private JsonNode postReqJsonNode;
private JsonNode patchReqJsonNode;
private JsonNode putReqJsonNode;
private JsonNode handlePostReqJsonNode;
private JsonNode doiPostReqJsonNode;
private JsonNode digitalSpecimenPostReqJsonNode;
private JsonNode digitalMediaPostReqJsonNode;
private JsonNode handleJsonNode;
private JsonNode doiJsonNode;
private JsonNode digitalSpecimenJsonNode;
private JsonNode digitalMediaJsonNode;
private JsonNode tombstoneReqJsonNode;
private JsonNode annotationPostReqJsonNode;
private JsonNode mappingPostReqJsonNode;
private JsonNode sourceSystemPostReqJsonNode;
private JsonNode organisationPostReqJsonNode;
private JsonNode masPostReqJsonNode;
private JsonNode annotationJsonNode;
private JsonNode mappingJsonNode;
private JsonNode sourceSystemJsonNode;
private JsonNode organisationJsonNode;
private JsonNode masJsonNode;

// Schemas
private JsonSchema postReqSchema;
private JsonSchema patchReqSchema;
private JsonSchema putReqSchema;
private JsonSchema handlePostReqSchema;
private JsonSchema doiPostReqSchema;
private JsonSchema digitalSpecimenPostReqSchema;
private JsonSchema digitalMediaPostReqSchema;
private JsonSchema handleSchema;
private JsonSchema doiSchema;
private JsonSchema digitalSpecimenSchema;
private JsonSchema digitalMediaSchema;
private JsonSchema tombstoneReqSchema;
private JsonSchema annotationPostReqSchema;
private JsonSchema mappingPostReqSchema;
private JsonSchema sourceSystemPostReqSchema;
private JsonSchema organisationPostReqSchema;
private JsonSchema masPostReqSchema;
private JsonSchema annotationSchema;
private JsonSchema dataMappingSchema;
private JsonSchema sourceSystemSchema;
private JsonSchema organisationSchema;
private JsonSchema masSchema;

public JsonSchemaValidator() {
setPostRequestAttributesJsonNodes();
Expand All @@ -80,16 +84,16 @@ public JsonSchemaValidator() {

private void setPostRequestAttributesJsonNodes() {
var schemaGenerator = new SchemaGenerator(jacksonModuleSchemaConfig());
handlePostReqJsonNode = schemaGenerator.generateSchema(HandleRecordRequest.class);
doiPostReqJsonNode = schemaGenerator.generateSchema(DoiRecordRequest.class);
digitalSpecimenPostReqJsonNode = schemaGenerator.generateSchema(DigitalSpecimenRequest.class);
digitalMediaPostReqJsonNode = schemaGenerator.generateSchema(DigitalMediaRequest.class);
handleJsonNode = schemaGenerator.generateSchema(HandleRecordRequest.class);
doiJsonNode = schemaGenerator.generateSchema(DoiRecordRequest.class);
digitalSpecimenJsonNode = schemaGenerator.generateSchema(DigitalSpecimenRequest.class);
digitalMediaJsonNode = schemaGenerator.generateSchema(DigitalMediaRequest.class);
tombstoneReqJsonNode = schemaGenerator.generateSchema(TombstoneRecordRequest.class);
annotationPostReqJsonNode = schemaGenerator.generateSchema(AnnotationRequest.class);
mappingPostReqJsonNode = schemaGenerator.generateSchema(DataMappingRequest.class);
sourceSystemPostReqJsonNode = schemaGenerator.generateSchema(SourceSystemRequest.class);
organisationPostReqJsonNode = schemaGenerator.generateSchema(OrganisationRequest.class);
masPostReqJsonNode = schemaGenerator.generateSchema(MasRequest.class);
annotationJsonNode = schemaGenerator.generateSchema(AnnotationRequest.class);
mappingJsonNode = schemaGenerator.generateSchema(DataMappingRequest.class);
sourceSystemJsonNode = schemaGenerator.generateSchema(SourceSystemRequest.class);
organisationJsonNode = schemaGenerator.generateSchema(OrganisationRequest.class);
masJsonNode = schemaGenerator.generateSchema(MasRequest.class);
}

private SchemaGeneratorConfig jacksonModuleSchemaConfig() {
Expand Down Expand Up @@ -132,7 +136,8 @@ private SchemaGeneratorConfig jacksonModuleSchemaConfig() {
private void setRequestJsonNodes() {
var schemaGenerator = new SchemaGenerator(requestSchemaConfig());
postReqJsonNode = schemaGenerator.generateSchema(PostRequest.class);
putReqJsonNode = schemaGenerator.generateSchema(PutRequest.class);
patchReqJsonNode = schemaGenerator.generateSchema(PatchRequest.class);
putReqJsonNode = schemaGenerator.generateSchema(TombstoneRequest.class);
}

public SchemaGeneratorConfig requestSchemaConfig() {
Expand Down Expand Up @@ -163,74 +168,72 @@ public SchemaGeneratorConfig requestSchemaConfig() {

private void setJsonSchemas() {
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012);

postReqSchema = factory.getSchema(postReqJsonNode);
patchReqSchema = factory.getSchema(patchReqJsonNode);
putReqSchema = factory.getSchema(putReqJsonNode);

handlePostReqSchema = factory.getSchema(handlePostReqJsonNode);
doiPostReqSchema = factory.getSchema(doiPostReqJsonNode);
digitalSpecimenPostReqSchema = factory.getSchema(digitalSpecimenPostReqJsonNode);
digitalMediaPostReqSchema = factory.getSchema(digitalMediaPostReqJsonNode);
annotationPostReqSchema = factory.getSchema(annotationPostReqJsonNode);
mappingPostReqSchema = factory.getSchema(mappingPostReqJsonNode);
sourceSystemPostReqSchema = factory.getSchema(sourceSystemPostReqJsonNode);
organisationPostReqSchema = factory.getSchema(organisationPostReqJsonNode);
masPostReqSchema = factory.getSchema(masPostReqJsonNode);
handleSchema = factory.getSchema(handleJsonNode);
doiSchema = factory.getSchema(doiJsonNode);
digitalSpecimenSchema = factory.getSchema(digitalSpecimenJsonNode);
digitalMediaSchema = factory.getSchema(digitalMediaJsonNode);
annotationSchema = factory.getSchema(annotationJsonNode);
dataMappingSchema = factory.getSchema(mappingJsonNode);
sourceSystemSchema = factory.getSchema(sourceSystemJsonNode);
organisationSchema = factory.getSchema(organisationJsonNode);
masSchema = factory.getSchema(masJsonNode);
tombstoneReqSchema = factory.getSchema(tombstoneReqJsonNode);

}

public void validatePostRequest(JsonNode requestRoot) throws InvalidRequestException {
var validationErrors = postReqSchema.validate(requestRoot);
if (!validationErrors.isEmpty()) {
throw new InvalidRequestException(setErrorMessage(validationErrors, "POST"));
throw new InvalidRequestException(setErrorMessage(validationErrors, "CREATE"));
}
var fdoType = FdoType.fromString(requestRoot.get(NODE_DATA).get(NODE_TYPE).asText());
validateAttributes(requestRoot, fdoType);
}

FdoType type = FdoType.fromString(requestRoot.get(NODE_DATA).get(NODE_TYPE).asText());
var attributes = requestRoot.get(NODE_DATA).get(NODE_ATTRIBUTES);
switch (type) {
case HANDLE -> validateRequestAttributes(attributes, handlePostReqSchema, type);
case DOI -> validateRequestAttributes(attributes, doiPostReqSchema, type);
case DIGITAL_SPECIMEN ->
validateRequestAttributes(attributes, digitalSpecimenPostReqSchema, type);
case DIGITAL_MEDIA -> validateRequestAttributes(attributes, digitalMediaPostReqSchema, type);
case ANNOTATION -> validateRequestAttributes(attributes, annotationPostReqSchema, type);
case DATA_MAPPING -> validateRequestAttributes(attributes, mappingPostReqSchema, type);
case SOURCE_SYSTEM -> validateRequestAttributes(attributes, sourceSystemPostReqSchema, type);
case ORGANISATION -> validateRequestAttributes(attributes, organisationPostReqSchema, type);
case MAS -> validateRequestAttributes(attributes, masPostReqSchema, type);
default ->
throw new InvalidRequestException("Invalid Request. Reason: Invalid type: " + type);
public void validatePatchRequest(JsonNode requestRoot) throws InvalidRequestException {
var validationErrors = patchReqSchema.validate(requestRoot);
if (!validationErrors.isEmpty()) {
throw new InvalidRequestException(
setErrorMessage(validationErrors, "UPDATE"));
}
var fdoType = FdoType.fromString(requestRoot.get(NODE_DATA).get(NODE_TYPE).asText());
validateAttributes(requestRoot, fdoType);
}

public void validatePutRequest(JsonNode requestRoot) throws InvalidRequestException {
var validationErrors = putReqSchema.validate(requestRoot);
if (!validationErrors.isEmpty()) {
throw new InvalidRequestException(
setErrorMessage(validationErrors, "PUT (tombstone)"));
setErrorMessage(validationErrors, "TOMBSTONE"));
}
var attributes = requestRoot.get(NODE_DATA).get(NODE_ATTRIBUTES);
validateTombstoneRequestAttributes(attributes);
validateAttributes(requestRoot, TOMBSTONE);
}


private void validateTombstoneRequestAttributes(JsonNode requestAttributes)
private void validateAttributes(JsonNode requestRoot, FdoType fdoType)
throws InvalidRequestException {
var validationErrors = tombstoneReqSchema.validate(requestAttributes);
if (!validationErrors.isEmpty()) {
throw new InvalidRequestException(
setErrorMessage(validationErrors, FdoType.TOMBSTONE.getDigitalObjectName(),
requestAttributes));
var requestAttributes = requestRoot.get(NODE_DATA).get(NODE_ATTRIBUTES);
JsonSchema schema;
switch (fdoType) {
case HANDLE -> schema = handleSchema;
case DOI -> schema = doiSchema;
case DIGITAL_SPECIMEN -> schema = digitalSpecimenSchema;
case DIGITAL_MEDIA -> schema = digitalMediaSchema;
case ANNOTATION -> schema = annotationSchema;
case DATA_MAPPING -> schema = dataMappingSchema;
case SOURCE_SYSTEM -> schema = sourceSystemSchema;
case ORGANISATION -> schema = organisationSchema;
case MAS -> schema = masSchema;
case TOMBSTONE -> schema = tombstoneReqSchema;
default ->
throw new InvalidRequestException("Invalid Request. Reason: Invalid type: " + fdoType);
}
}

private void validateRequestAttributes(JsonNode requestAttributes, JsonSchema schema,
FdoType type) throws InvalidRequestException {
var validationErrors = schema.validate(requestAttributes);
if (!validationErrors.isEmpty()) {
throw new InvalidRequestException(
setErrorMessage(validationErrors, type.getDigitalObjectName(), requestAttributes));
setErrorMessage(validationErrors, fdoType.getDigitalObjectName(),
requestAttributes));
}
}

Expand Down
Loading

0 comments on commit d23bf66

Please sign in to comment.