Skip to content

Commit

Permalink
feat: implement validation on negotiation DSP endpoints (#3370)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt authored Aug 18, 2023
1 parent fca3562 commit af579c3
Show file tree
Hide file tree
Showing 18 changed files with 737 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public Response requestCatalog(JsonObject jsonObject, @HeaderParam(AUTHORIZATION

var validation = validatorRegistry.validate(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE, jsonObject);
if (validation.failed()) {
monitor.debug(format("Bad Request, %s", verificationResult.getFailureMessages()));
monitor.debug(format("Bad Request, %s", validation.getFailureMessages()));
return error().badRequest();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ dependencies {
api(project(":extensions:common:http"))
api(project(":extensions:common:json-ld"))

implementation(project(":core:common:validator-core"))

implementation(libs.jakarta.rsApi)

testImplementation(project(":core:common:junit"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,29 @@
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationProtocolService;
import org.eclipse.edc.protocol.dsp.api.configuration.DspApiConfiguration;
import org.eclipse.edc.protocol.dsp.negotiation.api.controller.DspNegotiationApiController;
import org.eclipse.edc.protocol.dsp.negotiation.api.validation.ContractAgreementMessageValidator;
import org.eclipse.edc.protocol.dsp.negotiation.api.validation.ContractAgreementVerificationMessageValidator;
import org.eclipse.edc.protocol.dsp.negotiation.api.validation.ContractNegotiationEventMessageValidator;
import org.eclipse.edc.protocol.dsp.negotiation.api.validation.ContractNegotiationTerminationMessageValidator;
import org.eclipse.edc.protocol.dsp.negotiation.api.validation.ContractOfferMessageValidator;
import org.eclipse.edc.protocol.dsp.negotiation.api.validation.ContractRequestMessageValidator;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry;
import org.eclipse.edc.web.spi.WebService;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_AGREEMENT_MESSAGE;
import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_AGREEMENT_VERIFICATION_MESSAGE;
import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_NEGOTIATION_EVENT_MESSAGE;
import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_NEGOTIATION_TERMINATION_MESSAGE;
import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_OFFER_MESSAGE;
import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_REQUEST_MESSAGE;

/**
* Creates and registers the controller for dataspace protocol negotiation requests.
*/
Expand All @@ -46,6 +60,8 @@ public class DspNegotiationApiExtension implements ServiceExtension {
private Monitor monitor;
@Inject
private ContractNegotiationProtocolService protocolService;
@Inject
private JsonObjectValidatorRegistry validatorRegistry;

@Override
public String name() {
Expand All @@ -54,9 +70,17 @@ public String name() {

@Override
public void initialize(ServiceExtensionContext context) {
validatorRegistry.register(DSPACE_TYPE_CONTRACT_REQUEST_MESSAGE, ContractRequestMessageValidator.instance());
validatorRegistry.register(DSPACE_TYPE_CONTRACT_OFFER_MESSAGE, ContractOfferMessageValidator.instance());
validatorRegistry.register(DSPACE_TYPE_CONTRACT_NEGOTIATION_EVENT_MESSAGE, ContractNegotiationEventMessageValidator.instance());
validatorRegistry.register(DSPACE_TYPE_CONTRACT_AGREEMENT_MESSAGE, ContractAgreementMessageValidator.instance());
validatorRegistry.register(DSPACE_TYPE_CONTRACT_AGREEMENT_VERIFICATION_MESSAGE, ContractAgreementVerificationMessageValidator.instance());
validatorRegistry.register(DSPACE_TYPE_CONTRACT_NEGOTIATION_TERMINATION_MESSAGE, ContractNegotiationTerminationMessageValidator.instance());

var callbackAddress = apiConfiguration.getDspCallbackAddress();

var controller = new DspNegotiationApiController(callbackAddress, identityService, transformerRegistry, protocolService, monitor);
var controller = new DspNegotiationApiController(callbackAddress, identityService, transformerRegistry,
protocolService, monitor, validatorRegistry);

webService.registerResource(apiConfiguration.getContextAlias(), controller);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry;
import org.eclipse.edc.web.spi.exception.InvalidRequestException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -52,7 +53,6 @@

import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;
import static java.lang.String.format;
import static org.eclipse.edc.jsonld.spi.TypeUtil.isOfExpectedType;
import static org.eclipse.edc.protocol.dsp.negotiation.api.NegotiationApiPaths.AGREEMENT;
import static org.eclipse.edc.protocol.dsp.negotiation.api.NegotiationApiPaths.BASE_PATH;
import static org.eclipse.edc.protocol.dsp.negotiation.api.NegotiationApiPaths.CONTRACT_OFFER;
Expand Down Expand Up @@ -82,6 +82,7 @@ public class DspNegotiationApiController {

private final IdentityService identityService;
private final TypeTransformerRegistry transformerRegistry;
private final JsonObjectValidatorRegistry validatorRegistry;
private final String callbackAddress;
private final Monitor monitor;
private final ContractNegotiationProtocolService protocolService;
Expand All @@ -90,12 +91,14 @@ public DspNegotiationApiController(String callbackAddress,
IdentityService identityService,
TypeTransformerRegistry transformerRegistry,
ContractNegotiationProtocolService protocolService,
Monitor monitor) {
Monitor monitor,
JsonObjectValidatorRegistry validatorRegistry) {
this.callbackAddress = callbackAddress;
this.identityService = identityService;
this.monitor = monitor;
this.protocolService = protocolService;
this.transformerRegistry = transformerRegistry;
this.validatorRegistry = validatorRegistry;
}

/**
Expand Down Expand Up @@ -129,19 +132,14 @@ public Response getNegotiation(@PathParam("id") String id, @HeaderParam(AUTHORIZ
@Path(INITIAL_CONTRACT_REQUEST)
public Response initiateNegotiation(JsonObject jsonObject,
@HeaderParam(AUTHORIZATION) String token) {
var negotiationResult = handleMessage(MessageSpec.Builder.newInstance(ContractRequestMessage.class)
return handleMessage(MessageSpec.Builder.newInstance(ContractRequestMessage.class)
.expectedMessageType(DSPACE_TYPE_CONTRACT_REQUEST_MESSAGE)
.message(jsonObject)
.token(token)
.serviceCall(this::validateAndProcessRequest)
.build());

if (negotiationResult.failed()) {
return error()
.from(negotiationResult.getFailure());
}

return createNegotiationResponse(negotiationResult.getContent());
.build())
.map(this::createNegotiationResponse)
.orElse(f -> error().from(f));
}

/**
Expand Down Expand Up @@ -300,7 +298,9 @@ private <M extends ContractRemoteMessage> ServiceResult<ContractNegotiation> han
return ServiceResult.unauthorized(claimToken.getFailureMessages());
}

if (!isOfExpectedType(messageSpec.getMessage(), messageSpec.getExpectedMessageType())) {
var validation = validatorRegistry.validate(messageSpec.getExpectedMessageType(), messageSpec.getMessage());
if (validation.failed()) {
monitor.debug(format("Bad Request, %s", validation.getFailureMessages()));
return ServiceResult.badRequest(format("Request body was not of expected type: %s", messageSpec.getExpectedMessageType()));
}

Expand Down Expand Up @@ -361,5 +361,4 @@ private Function<ServiceFailure, Response> createErrorResponse(String id) {
private DspErrorResponse error() {
return DspErrorResponse.type(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.protocol.dsp.negotiation.api.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreementMessage;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.TypeIs;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_AGREEMENT_MESSAGE;

/**
* Validator for {@link ContractAgreementMessage} Json-LD representation
*/
public class ContractAgreementMessageValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(path -> new TypeIs(path, DSPACE_TYPE_CONTRACT_AGREEMENT_MESSAGE))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.protocol.dsp.negotiation.api.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreementVerificationMessage;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.TypeIs;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_AGREEMENT_VERIFICATION_MESSAGE;

/**
* Validator for {@link ContractAgreementVerificationMessage} Json-LD representation
*/
public class ContractAgreementVerificationMessageValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(path -> new TypeIs(path, DSPACE_TYPE_CONTRACT_AGREEMENT_VERIFICATION_MESSAGE))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.protocol.dsp.negotiation.api.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.agreement.ContractNegotiationEventMessage;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.TypeIs;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_NEGOTIATION_EVENT_MESSAGE;

/**
* Validator for {@link ContractNegotiationEventMessage} Json-LD representation
*/
public class ContractNegotiationEventMessageValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(path -> new TypeIs(path, DSPACE_TYPE_CONTRACT_NEGOTIATION_EVENT_MESSAGE))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.protocol.dsp.negotiation.api.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiationTerminationMessage;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.TypeIs;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_NEGOTIATION_TERMINATION_MESSAGE;

/**
* Validator for {@link ContractNegotiationTerminationMessage} Json-LD representation
*/
public class ContractNegotiationTerminationMessageValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(path -> new TypeIs(path, DSPACE_TYPE_CONTRACT_NEGOTIATION_TERMINATION_MESSAGE))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.protocol.dsp.negotiation.api.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractOfferMessage;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.TypeIs;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_OFFER_MESSAGE;

/**
* Validator for {@link ContractOfferMessage} Json-LD representation
*/
public class ContractOfferMessageValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(path -> new TypeIs(path, DSPACE_TYPE_CONTRACT_OFFER_MESSAGE))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.protocol.dsp.negotiation.api.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequestMessage;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.TypeIs;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.protocol.dsp.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_REQUEST_MESSAGE;

/**
* Validator for {@link ContractRequestMessage} Json-LD representation
*/
public class ContractRequestMessageValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(path -> new TypeIs(path, DSPACE_TYPE_CONTRACT_REQUEST_MESSAGE))
.build();
}
}
Loading

0 comments on commit af579c3

Please sign in to comment.