-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add agreement retirement function core * Add RetirementApi and EndToEnd tests * Improve EndToEnd tests * Added AgreementsRetirementEntry and refactored code * Adds API V3 interface and transformers from to and JsonObject * adds controller implementation and tests * Refactored EndToEnd tests to use api * refactored evaluation function logic to work with postValidators instead * Headers * Checkstyle * Refactor pgruntime * Added docs * adjusted namespaces * Review suggestions * Make retirementDate long * Refactor API delete tests * Fix transform tests * Add AgreementsRetirementService and refactor * Checkstyle * Rename Class * Some docs * Retry CI * exclude dep * remove provides annotation * improve API example * Split Store and Service providers in different extensions * Change isRetired and create validator class * make AgreementRetirementService into impl * make store return stream on findAll * use AbstractResultAssert * deps * doc leftover
- Loading branch information
1 parent
8072f87
commit 27e6b15
Showing
35 changed files
with
2,186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Agreements Retirement Extension | ||
|
||
This extension is introduced to allow a dataspace dataset provider to _prematurely_ retire an active contract agreement. | ||
|
||
Contract agreements are immutable entities by design. | ||
The word prematurely is used here since contract agreements should only expire once the contractual terms agreed upon between participants no longer holds. | ||
|
||
Even though the previous statements are valid, the need to prematurely retire an active contract agreement exists if, for example, | ||
the contract agreement is a digital representation of a physical agreement which might have changed via legal | ||
mechanisms, hence resulting in a new contract. The digital representation is no longer valid and shouldn't allow any data transfers. | ||
|
||
## Technical approach | ||
|
||
Since contract agreements are immutable, the following approach was used to represent a contract agreement retirement. | ||
|
||
A policy pre validator was introduced that checks if the attached contract agreement exists in the `AgreementRetirementStore`. | ||
If it exists, the validation is considered failed. | ||
|
||
This policy pre validator is registered both in the `policy-monitor` and `transfer` scopes. In both cases, a failed pre validation | ||
leads to transfer process termination. | ||
|
||
An API was created to enable dataset providers to manage `AgreementRetirementEntry` entities in the `AgreementRetirementStore` via an endpoint. | ||
|
||
## AgreementRetirementEntry schema | ||
|
||
An `AgreementRetirementEntry` is composed of: | ||
- A contract agreement id. | ||
- A retirement reason. | ||
- An agreement retirement timestamp. | ||
|
||
`AgreementRetirementEntry` entities can be managed via the `/retireagreements` endpoint of the data management API. | ||
Please refer to the swagger API spec for detailed examples on how to manage these entities. | ||
|
||
## Impact on active or new transfer processes | ||
|
||
Once a contract agreement is retired, all active transfer processes related with that agreement | ||
will be terminated. New transfer process requests made from the consumer using the retired agreement will also fail with an | ||
agreement is invalid message. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* 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. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
********************************************************************************/ | ||
|
||
plugins { | ||
`java-library` | ||
`maven-publish` | ||
} | ||
|
||
dependencies { | ||
api(project(":edc-extensions:agreements:retirement-evaluation-core")) | ||
api(project(":edc-extensions:agreements:retirement-evaluation-api")) | ||
api(project(":edc-extensions:agreements:retirement-evaluation-spi")) | ||
} |
43 changes: 43 additions & 0 deletions
43
edc-extensions/agreements/retirement-evaluation-api/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* 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. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
********************************************************************************/ | ||
|
||
plugins { | ||
`java-library` | ||
`maven-publish` | ||
id(libs.plugins.swagger.get().pluginId) | ||
} | ||
dependencies { | ||
|
||
implementation(project(":edc-extensions:agreements:retirement-evaluation-spi")) | ||
implementation(libs.edc.api.management.config) | ||
|
||
implementation(libs.jakarta.rsApi) | ||
|
||
testImplementation(testFixtures(libs.edc.core.jersey)) | ||
testImplementation(libs.edc.spi.core) | ||
testImplementation(libs.edc.junit) | ||
testImplementation(libs.restAssured) | ||
testImplementation(project(":edc-extensions:agreements:retirement-evaluation-spi")) | ||
} | ||
|
||
edcBuild { | ||
swagger { | ||
apiGroup.set("control-plane") | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
.../org/eclipse/tractusx/edc/agreements/retirement/api/AgreementsRetirementApiExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* 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. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
********************************************************************************/ | ||
|
||
package org.eclipse.tractusx.edc.agreements.retirement.api; | ||
|
||
import jakarta.json.Json; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Extension; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Inject; | ||
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 org.eclipse.edc.web.spi.configuration.ApiContext; | ||
import org.eclipse.tractusx.edc.agreements.retirement.api.transform.JsonObjectFromAgreementRetirementTransformer; | ||
import org.eclipse.tractusx.edc.agreements.retirement.api.transform.JsonObjectToAgreementsRetirementEntryTransformer; | ||
import org.eclipse.tractusx.edc.agreements.retirement.api.v3.AgreementsRetirementApiV3Controller; | ||
import org.eclipse.tractusx.edc.agreements.retirement.spi.service.AgreementsRetirementService; | ||
|
||
import java.util.Map; | ||
|
||
import static org.eclipse.tractusx.edc.agreements.retirement.api.AgreementsRetirementApiExtension.NAME; | ||
|
||
|
||
@Extension(value = NAME) | ||
public class AgreementsRetirementApiExtension implements ServiceExtension { | ||
|
||
public static final String NAME = "Contract Agreement Retirement API "; | ||
|
||
@Override | ||
public String name() { | ||
return NAME; | ||
} | ||
|
||
@Inject | ||
private WebService webService; | ||
@Inject | ||
private TypeTransformerRegistry transformerRegistry; | ||
@Inject | ||
private JsonObjectValidatorRegistry validator; | ||
@Inject | ||
private AgreementsRetirementService agreementsRetirementService; | ||
@Inject | ||
private Monitor monitor; | ||
|
||
@Override | ||
public void initialize(ServiceExtensionContext context) { | ||
var jsonFactory = Json.createBuilderFactory(Map.of()); | ||
var managementTypeTransformerRegistry = transformerRegistry.forContext("management-api"); | ||
|
||
managementTypeTransformerRegistry.register(new JsonObjectFromAgreementRetirementTransformer(jsonFactory)); | ||
managementTypeTransformerRegistry.register(new JsonObjectToAgreementsRetirementEntryTransformer()); | ||
|
||
webService.registerResource(ApiContext.MANAGEMENT, new AgreementsRetirementApiV3Controller(agreementsRetirementService, managementTypeTransformerRegistry, validator, monitor)); | ||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
...edc/agreements/retirement/api/transform/JsonObjectFromAgreementRetirementTransformer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* 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. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
********************************************************************************/ | ||
|
||
package org.eclipse.tractusx.edc.agreements.retirement.api.transform; | ||
|
||
import jakarta.json.JsonBuilderFactory; | ||
import jakarta.json.JsonObject; | ||
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; | ||
import org.eclipse.edc.transform.spi.TransformerContext; | ||
import org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import static org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry.AR_ENTRY_AGREEMENT_ID; | ||
import static org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry.AR_ENTRY_REASON; | ||
import static org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry.AR_ENTRY_RETIREMENT_DATE; | ||
|
||
public class JsonObjectFromAgreementRetirementTransformer extends AbstractJsonLdTransformer<AgreementsRetirementEntry, JsonObject> { | ||
|
||
private final JsonBuilderFactory jsonFactory; | ||
|
||
public JsonObjectFromAgreementRetirementTransformer(JsonBuilderFactory jsonFactory) { | ||
super(AgreementsRetirementEntry.class, JsonObject.class); | ||
this.jsonFactory = jsonFactory; | ||
} | ||
|
||
|
||
@Override | ||
public @Nullable JsonObject transform(@NotNull AgreementsRetirementEntry entry, @NotNull TransformerContext transformerContext) { | ||
return jsonFactory.createObjectBuilder() | ||
.add(AR_ENTRY_AGREEMENT_ID, entry.getAgreementId()) | ||
.add(AR_ENTRY_REASON, entry.getReason()) | ||
.add(AR_ENTRY_RETIREMENT_DATE, entry.getAgreementRetirementDate()) | ||
.build(); | ||
|
||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...agreements/retirement/api/transform/JsonObjectToAgreementsRetirementEntryTransformer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* 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. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
********************************************************************************/ | ||
|
||
package org.eclipse.tractusx.edc.agreements.retirement.api.transform; | ||
|
||
import jakarta.json.JsonObject; | ||
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; | ||
import org.eclipse.edc.transform.spi.TransformerContext; | ||
import org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import static org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry.AR_ENTRY_AGREEMENT_ID; | ||
import static org.eclipse.tractusx.edc.agreements.retirement.spi.types.AgreementsRetirementEntry.AR_ENTRY_REASON; | ||
|
||
public class JsonObjectToAgreementsRetirementEntryTransformer extends AbstractJsonLdTransformer<JsonObject, AgreementsRetirementEntry> { | ||
|
||
public JsonObjectToAgreementsRetirementEntryTransformer() { | ||
super(JsonObject.class, AgreementsRetirementEntry.class); | ||
} | ||
|
||
@Override | ||
public @Nullable AgreementsRetirementEntry transform(@NotNull JsonObject jsonObject, @NotNull TransformerContext context) { | ||
var entryBuilder = AgreementsRetirementEntry.Builder.newInstance(); | ||
entryBuilder.withAgreementId(transformString(jsonObject.get(AR_ENTRY_AGREEMENT_ID), context)); | ||
entryBuilder.withReason(transformString(jsonObject.get(AR_ENTRY_REASON), context)); | ||
return entryBuilder.build(); | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
...java/org/eclipse/tractusx/edc/agreements/retirement/api/v3/AgreementsRetirementApiV3.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* 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. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
********************************************************************************/ | ||
|
||
package org.eclipse.tractusx.edc.agreements.retirement.api.v3; | ||
|
||
import io.swagger.v3.oas.annotations.OpenAPIDefinition; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.Parameter; | ||
import io.swagger.v3.oas.annotations.info.Info; | ||
import io.swagger.v3.oas.annotations.media.ArraySchema; | ||
import io.swagger.v3.oas.annotations.media.Content; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import io.swagger.v3.oas.annotations.parameters.RequestBody; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import jakarta.json.JsonArray; | ||
import jakarta.json.JsonObject; | ||
import org.eclipse.edc.web.spi.ApiErrorDetail; | ||
|
||
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; | ||
|
||
@OpenAPIDefinition(info = @Info(description = "With this API clients can retire an active Contract Agreement. Clients can also list all retired agreements.", title = "Agreements Retirement API")) | ||
@Tag(name = "Agreements Retirement") | ||
public interface AgreementsRetirementApiV3 { | ||
|
||
|
||
@Operation(description = "Get all retired contract agreements.", | ||
responses = { | ||
@ApiResponse(responseCode = "200", description = "A list of retired contract agreements"), | ||
@ApiResponse(responseCode = "400", description = "Request body was malformed", | ||
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) | ||
}) | ||
JsonArray getAllRetiredV3(JsonObject querySpecJson); | ||
|
||
@Operation(description = "Removes a contract agreement from the retired list, reactivating it.", | ||
responses = { | ||
@ApiResponse(responseCode = "204", description = "The contract agreement is reactivated"), | ||
@ApiResponse(responseCode = "404", description = "No entry for the given agreementId was found"), | ||
@ApiResponse(responseCode = "400", description = "Request body was malformed", | ||
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) | ||
}) | ||
void reactivateRetiredV3(@Parameter(name = "agreementId", description = "The contract agreement id") String agreementId); | ||
|
||
@Operation(description = "Retires an active contract agreement.", | ||
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = RetirementSchema.class))), | ||
|
||
responses = { | ||
@ApiResponse(responseCode = "204", description = "The contract agreement was successfully retired"), | ||
@ApiResponse(responseCode = "409", description = "The contract agreement is already retired"), | ||
@ApiResponse(responseCode = "400", description = "Request body was malformed", | ||
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) | ||
}) | ||
void retireAgreementV3(JsonObject entry); | ||
|
||
|
||
@Schema(name = "Retirement Example", example = RetirementSchema.EXAMPLE) | ||
record RetirementSchema( | ||
@Schema(name = ID) String id, | ||
String reason | ||
) { | ||
public static final String EXAMPLE = """ | ||
{ | ||
"@context": { | ||
"tx": "https://w3id.org/tractusx/v0.0.1/ns/", | ||
"edc": "https://w3id.org/edc/v0.0.1/ns/" | ||
}, | ||
"edc:agreementId": "contract-agreement-id", | ||
"tx:reason": "This contract agreement was retired since the physical counterpart is no longer valid." | ||
} | ||
"""; | ||
} | ||
|
||
} |
Oops, something went wrong.