Skip to content

Commit

Permalink
fix: Abide to the DataOfferCreationRequest.PolicyEnum rule (#1055)
Browse files Browse the repository at this point in the history
  • Loading branch information
ununhexium authored Oct 4, 2024
1 parent a485964 commit 9f61ec9
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md).
#### Patch Changes

- Refactoring: Config as Java Code ([#1051](https://github.com/sovity/edc-ce/pull/1051))
- Fix issues with the Create Data Offer Endpoint ([PR#1055](https://github.com/sovity/edc-ce/pull/1055))

### Deployment Migration Notes

Expand Down
6 changes: 3 additions & 3 deletions docs/api/sovity-edc-api-wrapper.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -623,11 +623,11 @@ components:
DataSourceType:
type: string
description: Supported Data Source Types by UiDataSource
default: CUSTOM
enum:
- HTTP_DATA
- ON_REQUEST
- CUSTOM
default: CUSTOM
SecretValue:
type: object
properties:
Expand Down Expand Up @@ -835,14 +835,14 @@ components:
UiDataSourceHttpDataMethod:
type: string
description: Supported HTTP Methods by UiDataSource
default: GET
enum:
- GET
- POST
- PUT
- PATCH
- DELETE
- OPTIONS
default: GET
UiDataSourceOnRequest:
required:
- contactEmail
Expand Down Expand Up @@ -948,7 +948,7 @@ components:
$ref: '#/components/schemas/UiAssetCreateRequest'
policy:
type: string
description: Which policy to apply to this asset.
description: Which policy to apply to this asset creation.
enum:
- DONT_PUBLISH
- PUBLISH_UNRESTRICTED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class DataOfferCreationRequest {
@Schema(description = "The asset to create", requiredMode = REQUIRED)
private UiAssetCreateRequest uiAssetCreateRequest;

@Schema(description = "Which policy to apply to this asset.", requiredMode = REQUIRED)
@Schema(description = "Which policy to apply to this asset creation.", requiredMode = REQUIRED)
private PolicyDefinitionChoiceEnum policy;

@Schema(description = "Policy Expression.", requiredMode = NOT_REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@

package de.sovity.edc.ext.wrapper.api.ui.model;

import io.swagger.v3.oas.annotations.media.Schema;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

public enum PolicyDefinitionChoiceEnum {
@Schema(description = "Only create the asset", requiredMode = REQUIRED)
DONT_PUBLISH,
@Schema(description = "Create the asset and assigns the always-true policy in the contract definition", requiredMode = REQUIRED)
PUBLISH_UNRESTRICTED,
@Schema(description = "Create the asset, a policy and a contract definition", requiredMode = REQUIRED)
PUBLISH_RESTRICTED
}
3 changes: 3 additions & 0 deletions extensions/wrapper/wrapper/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ dependencies {
annotationProcessor(libs.lombok)
compileOnly(libs.lombok)


implementation(project(":config"))

api(project(":extensions:wrapper:wrapper-api"))
api(project(":extensions:wrapper:wrapper-common-mappers"))
api(project(":utils:catalog-parser"))
Expand All @@ -22,6 +24,7 @@ dependencies {

implementation(project(":extensions:contract-termination"))
implementation(project(":extensions:database-direct-access"))
implementation(project(":extensions:policy-always-true"))
implementation(project(":extensions:sovity-messenger"))
implementation(project(":utils:jooq-database-access"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry;
import org.eclipse.edc.protocol.dsp.api.configuration.DspApiConfiguration;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.spi.CoreConstants;
Expand Down Expand Up @@ -74,6 +75,8 @@ public class WrapperExtension implements ServiceExtension {
@Inject
private PolicyEngine policyEngine;
@Inject
private RuleBindingRegistry ruleBindingRegistry;
@Inject
private TransferProcessService transferProcessService;
@Inject
private TransferProcessStore transferProcessStore;
Expand Down Expand Up @@ -118,6 +121,7 @@ public void initialize(ServiceExtensionContext context) {
policyDefinitionService,
policyDefinitionStore,
policyEngine,
ruleBindingRegistry,
transferProcessService,
transferProcessStore,
typeTransformerRegistry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
import de.sovity.edc.ext.wrapper.controller.PlaceholderEndpointController;
import de.sovity.edc.extension.contacttermination.ContractAgreementTerminationService;
import de.sovity.edc.extension.db.directaccess.DslContextFactory;
import de.sovity.edc.extension.policy.services.AlwaysTruePolicyDefinitionService;
import de.sovity.edc.utils.catalog.DspCatalogService;
import de.sovity.edc.utils.catalog.mapper.DspDataOfferBuilder;
import de.sovity.edc.utils.config.ConfigProps;
Expand All @@ -97,6 +98,7 @@
import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.spi.asset.AssetIndex;
import org.eclipse.edc.spi.monitor.Monitor;
Expand Down Expand Up @@ -136,6 +138,7 @@ public static WrapperExtensionContext buildContext(
PolicyDefinitionService policyDefinitionService,
PolicyDefinitionStore policyDefinitionStore,
PolicyEngine policyEngine,
RuleBindingRegistry ruleBindingRegistry,
TransferProcessService transferProcessService,
TransferProcessStore transferProcessStore,
TypeTransformerRegistry typeTransformerRegistry
Expand Down Expand Up @@ -251,10 +254,14 @@ public static WrapperExtensionContext buildContext(
miwConfigBuilder,
selfDescriptionService
);
var alwaysTruePolicyService = new AlwaysTruePolicyDefinitionService(
policyDefinitionService
);
var dataOfferPageApiService = new DataOfferPageApiService(
assetApiService,
contractDefinitionApiService,
policyDefinitionApiService
policyDefinitionApiService,
alwaysTruePolicyService
);
var uiResource = new UiResourceImpl(
contractAgreementApiService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import de.sovity.edc.ext.wrapper.api.ui.pages.asset.AssetApiService;
import de.sovity.edc.ext.wrapper.api.ui.pages.contract_definitions.ContractDefinitionApiService;
import de.sovity.edc.ext.wrapper.api.ui.pages.policy.PolicyDefinitionApiService;
import de.sovity.edc.extension.policy.AlwaysTruePolicyConstants;
import de.sovity.edc.extension.policy.services.AlwaysTruePolicyDefinitionService;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.eclipse.edc.spi.types.domain.asset.Asset;
Expand All @@ -32,6 +34,7 @@ public class DataOfferPageApiService {
private final AssetApiService assetApiService;
private final ContractDefinitionApiService contractDefinitionApiService;
private final PolicyDefinitionApiService policyDefinitionApiService;
private final AlwaysTruePolicyDefinitionService alwaysTruePolicyDefinitionService;

@NotNull
public IdAvailabilityResponse checkIfPolicyIdAvailable(DSLContext dsl, String id) {
Expand Down Expand Up @@ -66,45 +69,106 @@ private boolean isIdAvailable(DSLContext dsl, Table<?> table, TableField<?, Stri
}

public IdResponseDto createDataOffer(DSLContext dsl, DataOfferCreationRequest dataOfferCreationRequest) {

val commonId = dataOfferCreationRequest.getUiAssetCreateRequest().getId();

val assetIdExists = checkIfAssetIdAvailable(dsl, commonId).isAvailable();
if (!assetIdExists) {
throw new InvalidRequestException("Asset with id %s already exists".formatted(commonId));
}
return switch (dataOfferCreationRequest.getPolicy()) {
case DONT_PUBLISH -> createButDontPublish(dsl, dataOfferCreationRequest, commonId);
case PUBLISH_UNRESTRICTED -> createAndPublishUnrestricted(dsl, dataOfferCreationRequest, commonId);
case PUBLISH_RESTRICTED -> createAndPublishRestricted(dsl, dataOfferCreationRequest, commonId);
};
}

val policyIdExists = checkIfPolicyIdAvailable(dsl, commonId).isAvailable();
if (!policyIdExists) {
throw new InvalidRequestException("Policy with id %s already exists".formatted(commonId));
private @NotNull IdResponseDto createAndPublishUnrestricted(
DSLContext dsl,
DataOfferCreationRequest dataOfferCreationRequest,
String commonId
) {
val assetId = commonId;
val contractDefinitionId = commonId;
val policyId = AlwaysTruePolicyConstants.POLICY_DEFINITION_ID;

checkAssetIdAvailable(dsl, assetId);
checkContractDefinitionIdAvailable(dsl, contractDefinitionId);

if (!alwaysTruePolicyDefinitionService.exists()) {
// the default always-true policy has been deleted, recreate it.
alwaysTruePolicyDefinitionService.create();
}

assetApiService.createAsset(dataOfferCreationRequest.getUiAssetCreateRequest());

return createContractDefinition(assetId, policyId, contractDefinitionId);
}

private @NotNull IdResponseDto createAndPublishRestricted(
DSLContext dsl,
DataOfferCreationRequest dataOfferCreationRequest,
String commonId
) {
val assetId = commonId;
val policyId = commonId;
val contractDefinitionId = commonId;

checkAssetIdAvailable(dsl, assetId);
checkPolicyIdAvailable(dsl, policyId);
checkContractDefinitionIdAvailable(dsl, contractDefinitionId);

assetApiService.createAsset(dataOfferCreationRequest.getUiAssetCreateRequest());

val policyExpression = Optional.ofNullable(dataOfferCreationRequest.getUiPolicyExpression())
.orElseThrow(() -> new InvalidRequestException("Missing policy expression"));
policyDefinitionApiService.createPolicyDefinitionV2(new PolicyDefinitionCreateDto(policyId, policyExpression));

createContractDefinition(assetId, policyId, contractDefinitionId);

return new IdResponseDto(commonId, OffsetDateTime.now());
}

private @NotNull IdResponseDto createButDontPublish(
DSLContext dsl,
DataOfferCreationRequest dataOfferCreationRequest,
String commonId
) {
checkAssetIdAvailable(dsl, commonId);
return assetApiService.createAsset(dataOfferCreationRequest.getUiAssetCreateRequest());
}

private void checkContractDefinitionIdAvailable(DSLContext dsl, String commonId) {
val contractDefinitionIdExists = checkIfContractDefinitionIdAvailable(dsl, commonId).isAvailable();
if (!contractDefinitionIdExists) {
throw new InvalidRequestException("Contract definition with id %s already exists".formatted(commonId));
}
}

assetApiService.createAsset(dataOfferCreationRequest.getUiAssetCreateRequest());

val maybeNewPolicy = Optional.ofNullable(dataOfferCreationRequest.getUiPolicyExpression());
private void checkPolicyIdAvailable(DSLContext dsl, String commonId) {
val policyIdExists = checkIfPolicyIdAvailable(dsl, commonId).isAvailable();
if (!policyIdExists) {
throw new InvalidRequestException("Policy with id %s already exists".formatted(commonId));
}
}

maybeNewPolicy.ifPresent(
policy -> policyDefinitionApiService.createPolicyDefinitionV2(new PolicyDefinitionCreateDto(commonId, policy)));
private void checkAssetIdAvailable(DSLContext dsl, String commonId) {
val assetIdExists = checkIfAssetIdAvailable(dsl, commonId).isAvailable();
if (!assetIdExists) {
throw new InvalidRequestException("Asset with id %s already exists".formatted(commonId));
}
}

private @NotNull IdResponseDto createContractDefinition(String assetId, String policyId, String contractDefinitionId) {
val cd = new ContractDefinitionRequest();
cd.setAssetSelector(List.of(UiCriterion.builder()
.operandLeft(Asset.PROPERTY_ID)
.operator(UiCriterionOperator.EQ)
.operandRight(UiCriterionLiteral.builder()
.type(UiCriterionLiteralType.VALUE)
.value(commonId)
.value(assetId)
.build())
.build()));
cd.setAccessPolicyId(commonId);
cd.setContractPolicyId(commonId);
cd.setContractDefinitionId(commonId);
cd.setAccessPolicyId(policyId);
cd.setContractPolicyId(policyId);
cd.setContractDefinitionId(contractDefinitionId);

contractDefinitionApiService.createContractDefinition(cd);

return new IdResponseDto(commonId, OffsetDateTime.now());
return contractDefinitionApiService.createContractDefinition(cd);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class AlwaysTrueMigrationTest {
private static final E2eTestExtension E2E_TEST_EXTENSION = new E2eTestExtension(
withModule(":launchers:connectors:sovity-dev").toBuilder()
.consumerConfigCustomizer(config -> config.setProperty(
ConfigProps.EDC_FLYWAY_ADDITIONAL_MIGRATION_LOCATIONS, "classpath:db/additional-test-data/always-true-policy-legacy"
ConfigProps.EDC_FLYWAY_ADDITIONAL_MIGRATION_LOCATIONS, "classpath:db/additional-test-data/always-true-policy-migrated"
))
.providerConfigCustomizer(config -> config.setProperty(
ConfigProps.EDC_FLYWAY_ADDITIONAL_MIGRATION_LOCATIONS, "classpath:db/additional-test-data/always-true-policy-migrated"
ConfigProps.EDC_FLYWAY_ADDITIONAL_MIGRATION_LOCATIONS, "classpath:db/additional-test-data/always-true-policy-legacy"
))
.build()
);
Expand Down
Loading

0 comments on commit 9f61ec9

Please sign in to comment.