Skip to content

Commit

Permalink
feat: validate contract negotiation api controller (#3196)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt committed Jun 20, 2023
1 parent 4434a84 commit 9d45f57
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 282 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.eclipse.edc.boot.system.injection.InjectorImpl;
import org.eclipse.edc.boot.system.injection.ReflectiveObjectFactory;
import org.eclipse.edc.boot.system.runtime.BaseRuntime;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.injection.InjectionPointScanner;
import org.eclipse.edc.spi.system.injection.ObjectFactory;
Expand Down Expand Up @@ -63,7 +64,10 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon
return true;
} else if (type.equals(ServiceExtensionContext.class)) {
return true;
} else if (type instanceof Class) {
} else if (type instanceof Class<?> clazz) {
if (ServiceExtension.class.isAssignableFrom(clazz)) {
return true;
}
return context.hasService(cast(type));
}
return false;
Expand All @@ -76,7 +80,10 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
return context;
} else if (type.equals(ObjectFactory.class)) {
return factory;
} else if (type instanceof Class) {
} else if (type instanceof Class<?> clazz) {
if (ServiceExtension.class.isAssignableFrom(clazz)) {
return factory.constructInstance(clazz);
}
return context.getService(cast(type));
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
api(project(":spi:common:transaction-spi"))
implementation(project(":extensions:common:api:api-core"))
implementation(project(":extensions:common:api:management-api-configuration"))
implementation(project(":core:common:validator-core"))

implementation(libs.jakarta.rsApi)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@
import org.eclipse.edc.spi.query.QuerySpec;
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.eclipse.edc.web.spi.exception.ObjectNotFoundException;
import org.eclipse.edc.web.spi.exception.ValidationFailureException;

import java.util.Optional;

import static jakarta.json.stream.JsonCollectors.toJsonArray;
import static java.util.Optional.ofNullable;
import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper;

@Consumes({ MediaType.APPLICATION_JSON })
Expand All @@ -56,24 +57,33 @@ public class ContractNegotiationApiController implements ContractNegotiationApi
private final ContractNegotiationService service;
private final TypeTransformerRegistry transformerRegistry;
private final Monitor monitor;
private final JsonObjectValidatorRegistry validatorRegistry;

public ContractNegotiationApiController(ContractNegotiationService service, TypeTransformerRegistry transformerRegistry, Monitor monitor) {
public ContractNegotiationApiController(ContractNegotiationService service, TypeTransformerRegistry transformerRegistry,
Monitor monitor, JsonObjectValidatorRegistry validatorRegistry) {
this.service = service;
this.transformerRegistry = transformerRegistry;
this.monitor = monitor;
this.validatorRegistry = validatorRegistry;
}

@POST
@Path("/request")
@Override
public JsonArray queryNegotiations(JsonObject querySpecDto) {
var spec = ofNullable(querySpecDto)
.map(json -> transformerRegistry.transform(json, QuerySpecDto.class)
.compose(dto -> transformerRegistry.transform(dto, QuerySpec.class)))
.orElse(Result.success(QuerySpec.Builder.newInstance().build()))
.orElseThrow(InvalidRequestException::new);
QuerySpec querySpec;
if (querySpecDto == null) {
querySpec = QuerySpec.Builder.newInstance().build();
} else {
validatorRegistry.validate(QuerySpecDto.EDC_QUERY_SPEC_TYPE, querySpecDto)
.orElseThrow(ValidationFailureException::new);

querySpec = transformerRegistry.transform(querySpecDto, QuerySpecDto.class)
.compose(dto -> transformerRegistry.transform(dto, QuerySpec.class))
.orElseThrow(InvalidRequestException::new);
}

try (var stream = service.query(spec).orElseThrow(exceptionMapper(ContractNegotiation.class, null))) {
try (var stream = service.query(querySpec).orElseThrow(exceptionMapper(ContractNegotiation.class, null))) {
return stream
.map(it -> transformerRegistry.transform(it, ContractNegotiationDto.class)
.compose(dto -> transformerRegistry.transform(dto, JsonObject.class)))
Expand Down Expand Up @@ -124,6 +134,9 @@ public JsonObject getAgreementForNegotiation(@PathParam("id") String negotiation
@POST
@Override
public JsonObject initiateContractNegotiation(JsonObject requestObject) {
validatorRegistry.validate(NegotiationInitiateRequestDto.TYPE, requestObject)
.orElseThrow(ValidationFailureException::new);

var contractRequest = transformerRegistry.transform(requestObject, NegotiationInitiateRequestDto.class)
.compose(dto -> transformerRegistry.transform(dto, ContractRequest.class))
.orElseThrow(InvalidRequestException::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import jakarta.json.Json;
import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration;
import org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationInitiateRequestDto;
import org.eclipse.edc.connector.api.management.contractnegotiation.transform.ContractAgreementToContractAgreementDtoTransformer;
import org.eclipse.edc.connector.api.management.contractnegotiation.transform.ContractNegotiationToContractNegotiationDtoTransformer;
import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectFromContractAgreementDtoTransformer;
Expand All @@ -25,12 +26,14 @@
import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferDescriptionTransformer;
import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToNegotiationInitiateRequestDtoTransformer;
import org.eclipse.edc.connector.api.management.contractnegotiation.transform.NegotiationInitiateRequestDtoToDataRequestTransformer;
import org.eclipse.edc.connector.api.management.contractnegotiation.validation.NegotiationInitiateRequestDtoValidator;
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
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 java.time.Clock;
Expand All @@ -56,6 +59,9 @@ public class ContractNegotiationApiExtension implements ServiceExtension {
@Inject
private Clock clock;

@Inject
private JsonObjectValidatorRegistry validatorRegistry;

@Override
public String name() {
return NAME;
Expand All @@ -73,8 +79,11 @@ public void initialize(ServiceExtensionContext context) {
transformerRegistry.register(new JsonObjectFromNegotiationStateTransformer(factory));
transformerRegistry.register(new JsonObjectToContractOfferDescriptionTransformer());

validatorRegistry.register(NegotiationInitiateRequestDto.TYPE, NegotiationInitiateRequestDtoValidator.instance());

var monitor = context.getMonitor();

webService.registerResource(config.getContextAlias(), new ContractNegotiationApiController(service, transformerRegistry, monitor));
var controller = new ContractNegotiationApiController(service, transformerRegistry, monitor, validatorRegistry);
webService.registerResource(config.getContextAlias(), controller);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,8 @@

package org.eclipse.edc.connector.api.management.contractnegotiation.model;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import org.eclipse.edc.policy.model.Policy;

import java.util.concurrent.TimeUnit;

import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;

public class ContractOfferDescription {
Expand All @@ -31,21 +26,10 @@ public class ContractOfferDescription {
public static final String ASSET_ID = EDC_NAMESPACE + "assetId";
public static final String POLICY = EDC_NAMESPACE + "policy";

/**
* Default validity is set to one year.
*/
private static final long DEFAULT_VALIDITY = TimeUnit.DAYS.toSeconds(365);

@NotBlank(message = "offerId is mandatory")
private String offerId;
@NotBlank(message = "assetId is mandatory")
private String assetId;
@NotNull(message = "policy cannot be null")
private Policy policy;

@Positive(message = "validity must be positive")
private long validity = DEFAULT_VALIDITY;

private ContractOfferDescription() {
}

Expand All @@ -61,10 +45,6 @@ public Policy getPolicy() {
return policy;
}

public long getValidity() {
return validity;
}

public static final class Builder {
private final ContractOfferDescription dto;

Expand All @@ -91,11 +71,6 @@ public ContractOfferDescription.Builder policy(Policy policy) {
return this;
}

public ContractOfferDescription.Builder validity(long validity) {
dto.validity = validity;
return this;
}

public ContractOfferDescription build() {
return dto;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

package org.eclipse.edc.connector.api.management.contractnegotiation.model;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.eclipse.edc.api.model.BaseDto;
import org.eclipse.edc.spi.types.domain.callback.CallbackAddress;

Expand All @@ -33,17 +31,10 @@ public class NegotiationInitiateRequestDto extends BaseDto {
public static final String CONSUMER_ID = EDC_NAMESPACE + "consumerId";
public static final String OFFER = EDC_NAMESPACE + "offer";
public static final String CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses";
public static final String OFFER_ID = EDC_NAMESPACE + "offerId";
public static final String ASSET_ID = EDC_NAMESPACE + "assetId";
public static final String POLICY = EDC_NAMESPACE + "policy";

@NotBlank(message = "connectorAddress is mandatory")
private String connectorAddress; // TODO change to callbackAddress
@NotBlank(message = "protocol is mandatory")
private String protocol;
@NotBlank(message = "connectorId is mandatory")
private String connectorId;
@NotNull(message = "offer cannot be null")
private ContractOfferDescription offer;
private String providerId;
private String consumerId;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.connector.api.management.contractnegotiation.validation;

import jakarta.json.JsonObject;
import org.eclipse.edc.validator.jsonobject.JsonObjectValidator;
import org.eclipse.edc.validator.jsonobject.validators.MandatoryObject;
import org.eclipse.edc.validator.jsonobject.validators.MandatoryValue;
import org.eclipse.edc.validator.spi.Validator;

import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID;
import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID;
import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY;
import static org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationInitiateRequestDto.CONNECTOR_ADDRESS;
import static org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationInitiateRequestDto.CONNECTOR_ID;
import static org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationInitiateRequestDto.OFFER;
import static org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationInitiateRequestDto.PROTOCOL;

public class NegotiationInitiateRequestDtoValidator {
public static Validator<JsonObject> instance() {
return JsonObjectValidator.newValidator()
.verify(CONNECTOR_ADDRESS, MandatoryValue::new)
.verify(PROTOCOL, MandatoryValue::new)
.verify(CONNECTOR_ID, MandatoryValue::new)
.verify(OFFER, MandatoryObject::new)
.verifyObject(OFFER, v -> v
.verify(OFFER_ID, MandatoryValue::new)
.verify(ASSET_ID, MandatoryValue::new)
.verify(POLICY, MandatoryObject::new)
)
.build();
}
}
Loading

0 comments on commit 9d45f57

Please sign in to comment.