diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityTrustTransformExtension.java b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityTrustTransformExtension.java index a67ad1c9bb2..5ca0b40dbda 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityTrustTransformExtension.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityTrustTransformExtension.java @@ -28,6 +28,7 @@ import org.eclipse.edc.jsonld.spi.JsonLd; 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.result.Result; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; @@ -35,12 +36,13 @@ import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.jetbrains.annotations.NotNull; -import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.util.Map; import static java.lang.String.format; import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DCP_CONTEXT_URL; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_V_1_0_CONTEXT; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; @Extension(value = IdentityTrustTransformExtension.NAME, categories = { "iam", "transform", "jsonld" }) @@ -55,23 +57,24 @@ public class IdentityTrustTransformExtension implements ServiceExtension { @Inject private TypeManager typeManager; + @Inject + private Monitor monitor; + @Override public void initialize(ServiceExtensionContext context) { - getResourceUri("document" + File.separator + "credentials.v2.jsonld") - .onSuccess(uri -> jsonLdService.registerCachedDocument("https://www.w3.org/2018/credentials/v2", uri)) - .onFailure(failure -> context.getMonitor().warning("Failed to register cached json-ld document: " + failure.getFailureDetail())); - getResourceUri("document" + File.separator + "credentials.v1.jsonld") - .onSuccess(uri -> jsonLdService.registerCachedDocument("https://www.w3.org/2018/credentials/v1", uri)) - .onFailure(failure -> context.getMonitor().warning("Failed to register cached json-ld document: " + failure.getFailureDetail())); + var contexts = Map.of("credentials.v2.jsonld", "https://www.w3.org/2018/credentials/v2", + "credentials.v1.jsonld", "https://www.w3.org/2018/credentials/v1", + "dcp.v08.jsonld", DCP_CONTEXT_URL, + "dcp.v1.0.jsonld", DSPACE_DCP_V_1_0_CONTEXT); - getResourceUri("document" + File.separator + "dcp.v08.jsonld") - .onSuccess(uri -> jsonLdService.registerCachedDocument(DCP_CONTEXT_URL, uri)) - .onFailure(failure -> context.getMonitor().warning("Failed to register cached json-ld document: " + failure.getFailureDetail())); + contexts.forEach((key, value) -> getResourceUri("document/" + key) + .onSuccess(uri -> jsonLdService.registerCachedDocument(value, uri)) + .onFailure(failure -> monitor.warning("Failed to register cached json-ld document: " + failure.getFailureDetail()))); typeTransformerRegistry.register(new JsonObjectToPresentationQueryTransformer(typeManager, JSON_LD)); typeTransformerRegistry.register(new JsonObjectToPresentationResponseMessageTransformer(typeManager, JSON_LD)); - typeTransformerRegistry.register(new JsonObjectFromPresentationQueryTransformer()); + typeTransformerRegistry.register(new JsonObjectFromPresentationQueryTransformer(typeManager, JSON_LD)); typeTransformerRegistry.register(new JsonObjectFromPresentationResponseMessageTransformer()); typeTransformerRegistry.register(new JsonObjectToVerifiablePresentationTransformer()); typeTransformerRegistry.register(new JsonObjectToVerifiableCredentialTransformer()); @@ -95,4 +98,5 @@ private Result getResourceUri(String name) { return Result.failure(format("Cannot read resource %s: %s", name, e.getMessage())); } } + } diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java index ffd8e32f812..317ac045caa 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java @@ -155,7 +155,7 @@ private JsonObject createPresentationQuery(List scopes) { .add(JsonLdKeywords.CONTEXT, jsonFactory.createArrayBuilder() .add(VcConstants.PRESENTATION_EXCHANGE_URL) .add(DcpConstants.DCP_CONTEXT_URL)) - .add(JsonLdKeywords.TYPE, PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_TYPE) + .add(JsonLdKeywords.TYPE, PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_TERM) .add("scope", scopeArray.build()) .build(); } diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/resources/document/dcp.v1.0.jsonld b/extensions/common/iam/identity-trust/identity-trust-core/src/main/resources/document/dcp.v1.0.jsonld new file mode 100644 index 00000000000..f7858e3423d --- /dev/null +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/resources/document/dcp.v1.0.jsonld @@ -0,0 +1,137 @@ +{ + "@context": { + "@version": 1.1, + "@protected": true, + "dcp": "https://w3id.org/dspace-dcp/v1.0/", + "cred": "https://www.w3.org/2018/credentials/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "id": "@id", + "type": "@type", + "CredentialContainer": { + "@id": "dcp:CredentialContainer", + "@context": { + "payload": { + "@id": "dcp:payload", + "@type": "xsd:string" + } + } + }, + "CredentialMessage": { + "@id": "dcp:CredentialMessage", + "@context": { + "credentials": { + "@id": "dcp:credentials", + "@container": "@set" + }, + "requestId": { + "@id": "dcp:requestId", + "@type": "@id" + } + } + }, + "CredentialObject": { + "@id": "dcp:CredentialObject", + "@context": { + "credentialType": { + "@id": "dcp:credentialType", + "@container": "@set" + }, + "offerReason": { + "@id": "dcp:offerReason", + "@type": "xsd:string" + }, + "bindingMethods": { + "@id": "dcp:bindingMethods", + "@type": "xsd:string", + "@container": "@set" + }, + "profiles": { + "@id": "dcp:profiles", + "@type": "xsd:string", + "@container": "@set" + }, + "issuancePolicy": { + "@id": "dcp:issuancePolicy", + "@type": "@json" + } + } + }, + "CredentialOfferMessage": { + "@id": "dcp:CredentialOfferMessage", + "@context": { + "credentialIssuer": "cred:issuer", + "credentials": { + "@id": "dcp:credentials", + "@container": "@set" + } + } + }, + "CredentialRequestMessage": { + "@id": "dcp:CredentialRequestMessage", + "@context": { + "format": "dcp:format", + "credentialType": { + "@id": "dcp:credentialType", + "@type": "@vocab", + "@container": "@set" + } + } + }, + "CredentialService": "dcp:CredentialService", + "CredentialStatus": { + "@id": "dcp:CredentialStatus", + "@context": { + "requestId": { + "@id": "dcp:requestId", + "@type": "@id" + }, + "status": { + "@id": "dcp:status", + "@type": "@vocab" + }, + "RECEIVED": "dcp:RECEIVED", + "REJECTED": "dcp:REJECTED", + "ISSUED": "dcp:ISSUED" + } + }, + "IssuerMetadata": { + "@id": "dcp:IssuerMetadata", + "@context": { + "credentialIssuer": "cred:issuer", + "credentialsSupported": { + "@id": "dcp:credentialsSupported", + "@container": "@set" + } + } + }, + "IssuerService": "dcp:IssuerService", + "PresentationQueryMessage": { + "@id": "dcp:PresentationQueryMessage", + "@context": { + "presentationDefinition": { + "@id": "dcp:presentationDefinition", + "@type": "@json" + }, + "scope": { + "@id": "dcp:scope", + "@type": "xsd:string", + "@container": "@set" + } + } + }, + "PresentationResponseMessage": { + "@id": "dcp:PresentationResponseMessage", + "@context": { + "presentation": { + "@id": "dcp:presentation", + "@container": "@set", + "@type": "@json" + }, + "presentationSubmission": { + "@id": "dcp:presentationSubmission", + "@type": "@json" + } + } + } + } +} \ No newline at end of file diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformer.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformer.java index 91514a4f9f6..a7ca2737521 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformer.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformer.java @@ -14,21 +14,51 @@ package org.eclipse.edc.iam.identitytrust.transform.from; +import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.jsonld.spi.JsonLdKeywords; +import org.eclipse.edc.jsonld.spi.JsonLdNamespace; +import org.eclipse.edc.jsonld.spi.transformer.AbstractNamespaceAwareJsonLdTransformer; +import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TransformerContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class JsonObjectFromPresentationQueryTransformer extends AbstractJsonLdTransformer { +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_0_8; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_SCOPE_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_TERM; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; - public JsonObjectFromPresentationQueryTransformer() { - super(PresentationQueryMessage.class, JsonObject.class); +public class JsonObjectFromPresentationQueryTransformer extends AbstractNamespaceAwareJsonLdTransformer { + private final TypeManager typeManager; + private final String typeContext; + + public JsonObjectFromPresentationQueryTransformer(TypeManager typeManager, String typeContext) { + this(typeManager, typeContext, DSPACE_DCP_NAMESPACE_V_0_8); + } + + public JsonObjectFromPresentationQueryTransformer(TypeManager typeManager, String typeContext, JsonLdNamespace namespace) { + super(PresentationQueryMessage.class, JsonObject.class, namespace); + this.typeManager = typeManager; + this.typeContext = typeContext; } @Override public @Nullable JsonObject transform(@NotNull PresentationQueryMessage presentationQueryMessage, @NotNull TransformerContext context) { - return null; + var builder = Json.createObjectBuilder() + .add(TYPE, forNamespace(PRESENTATION_QUERY_MESSAGE_TERM)); + + if (presentationQueryMessage.getPresentationDefinition() != null) { + var presentationDefinition = Json.createObjectBuilder(); + presentationDefinition.add(JsonLdKeywords.VALUE, typeManager.getMapper(typeContext).convertValue(presentationQueryMessage.getPresentationDefinition(), JsonObject.class)); + presentationDefinition.add(JsonLdKeywords.TYPE, JsonLdKeywords.JSON); + builder.add(forNamespace(PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM), presentationDefinition); + } else { + builder.add(forNamespace(PRESENTATION_QUERY_MESSAGE_SCOPE_TERM), Json.createArrayBuilder(presentationQueryMessage.getScopes())); + } + return builder.build(); + } } diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformer.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformer.java index e51dd2f7438..1dd8d747e9c 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformer.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformer.java @@ -18,30 +18,36 @@ import jakarta.json.JsonObject; import org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage; import org.eclipse.edc.jsonld.spi.JsonLdKeywords; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.jsonld.spi.JsonLdNamespace; +import org.eclipse.edc.jsonld.spi.transformer.AbstractNamespaceAwareJsonLdTransformer; import org.eclipse.edc.transform.spi.TransformerContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY; -import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_0_8; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; /** * Transforms a {@link PresentationResponseMessage} into a {@link JsonObject} object. */ -public class JsonObjectFromPresentationResponseMessageTransformer extends AbstractJsonLdTransformer { +public class JsonObjectFromPresentationResponseMessageTransformer extends AbstractNamespaceAwareJsonLdTransformer { public JsonObjectFromPresentationResponseMessageTransformer() { - super(PresentationResponseMessage.class, JsonObject.class); + this(DSPACE_DCP_NAMESPACE_V_0_8); + } + + public JsonObjectFromPresentationResponseMessageTransformer(JsonLdNamespace namespace) { + super(PresentationResponseMessage.class, JsonObject.class, namespace); } @Override public @Nullable JsonObject transform(@NotNull PresentationResponseMessage responseMessage, @NotNull TransformerContext context) { // Presentation Submission not supported yet return Json.createObjectBuilder() - .add(TYPE, PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY) - .add(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY, createJson(responseMessage)) + .add(TYPE, forNamespace(PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM)) + .add(forNamespace(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM), createJson(responseMessage)) .build(); } diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryTransformer.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryTransformer.java index 8ea6e7e80af..253a57bebdd 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryTransformer.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryTransformer.java @@ -21,7 +21,8 @@ import org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage; import org.eclipse.edc.iam.verifiablecredentials.spi.model.presentationdefinition.PresentationDefinition; import org.eclipse.edc.jsonld.spi.JsonLdKeywords; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.jsonld.spi.JsonLdNamespace; +import org.eclipse.edc.jsonld.spi.transformer.AbstractNamespaceAwareJsonLdTransformer; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TransformerContext; import org.jetbrains.annotations.NotNull; @@ -29,16 +30,24 @@ import java.util.List; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_0_8; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_SCOPE_TERM; + /** * Transforms a JsonObject into a PresentationQuery object. */ -public class JsonObjectToPresentationQueryTransformer extends AbstractJsonLdTransformer { +public class JsonObjectToPresentationQueryTransformer extends AbstractNamespaceAwareJsonLdTransformer { private final TypeManager typeManager; private final String typeContext; public JsonObjectToPresentationQueryTransformer(TypeManager typeManager, String typeContext) { - super(JsonObject.class, PresentationQueryMessage.class); + this(typeManager, typeContext, DSPACE_DCP_NAMESPACE_V_0_8); + } + + public JsonObjectToPresentationQueryTransformer(TypeManager typeManager, String typeContext, JsonLdNamespace namespace) { + super(JsonObject.class, PresentationQueryMessage.class, namespace); this.typeManager = typeManager; this.typeContext = typeContext; } @@ -46,15 +55,16 @@ public JsonObjectToPresentationQueryTransformer(TypeManager typeManager, String @Override public @Nullable PresentationQueryMessage transform(@NotNull JsonObject jsonObject, @NotNull TransformerContext context) { var bldr = PresentationQueryMessage.Builder.newinstance(); - visitProperties(jsonObject, (k, v) -> { - switch (k) { - case PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_DEFINITION_PROPERTY -> - bldr.presentationDefinition(readPresentationDefinition(v, context)); - case PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_SCOPE_PROPERTY -> - transformArrayOrObject(v, Object.class, o -> bldr.scopes(List.of(o.toString().split(" "))), context); - default -> context.reportProblem("Unknown property '%s'".formatted(k)); - } - }); + + var definition = jsonObject.get(forNamespace(PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM)); + if (definition != null) { + bldr.presentationDefinition(readPresentationDefinition(definition, context)); + } + + var scopes = jsonObject.get(forNamespace(PRESENTATION_QUERY_MESSAGE_SCOPE_TERM)); + if (scopes != null) { + transformArrayOrObject(scopes, Object.class, o -> bldr.scopes(List.of(o.toString().split(" "))), context); + } return bldr.build(); } diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformer.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformer.java index fd8a5ea17f8..16db9bff2b3 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformer.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/main/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformer.java @@ -22,7 +22,8 @@ import org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage; import org.eclipse.edc.iam.verifiablecredentials.spi.model.credentialservice.PresentationSubmission; import org.eclipse.edc.jsonld.spi.JsonLdKeywords; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.jsonld.spi.JsonLdNamespace; +import org.eclipse.edc.jsonld.spi.transformer.AbstractNamespaceAwareJsonLdTransformer; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TransformerContext; import org.jetbrains.annotations.NotNull; @@ -30,32 +31,41 @@ import java.util.List; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_0_8; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.Builder; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_SUBMISSION_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM; + /** * Transforms a {@link JsonObject} into a {@link PresentationResponseMessage} object. */ -public class JsonObjectToPresentationResponseMessageTransformer extends AbstractJsonLdTransformer { +public class JsonObjectToPresentationResponseMessageTransformer extends AbstractNamespaceAwareJsonLdTransformer { private final TypeManager typeManager; private final String typeContext; public JsonObjectToPresentationResponseMessageTransformer(TypeManager typeManager, String typeContext) { - super(JsonObject.class, PresentationResponseMessage.class); + this(typeManager, typeContext, DSPACE_DCP_NAMESPACE_V_0_8); + } + + public JsonObjectToPresentationResponseMessageTransformer(TypeManager typeManager, String typeContext, JsonLdNamespace namespace) { + super(JsonObject.class, PresentationResponseMessage.class, namespace); this.typeManager = typeManager; this.typeContext = typeContext; } @Override public @Nullable PresentationResponseMessage transform(@NotNull JsonObject jsonObject, @NotNull TransformerContext context) { - var builder = PresentationResponseMessage.Builder.newinstance(); - visitProperties(jsonObject, (k, v) -> { - switch (k) { - case PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_SUBMISSION_PROPERTY -> - builder.presentationSubmission(readPresentationSubmission(v, context)); - case PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY -> - builder.presentation(readPresentation(v, context)); - default -> context.reportProblem("Unknown property '%s'".formatted(k)); - } - }); + var builder = Builder.newinstance(); + var submission = jsonObject.get(forNamespace(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_SUBMISSION_TERM)); + if (submission != null) { + builder.presentationSubmission(readPresentationSubmission(submission, context)); + } + + var presentation = jsonObject.get(forNamespace(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM)); + if (presentation != null) { + builder.presentation(readPresentation(presentation, context)); + } return builder.build(); } diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/TestContextProvider.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/TestContextProvider.java new file mode 100644 index 00000000000..fc2bfb5d6c0 --- /dev/null +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/TestContextProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Cofinity-X + * + * 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: + * Cofinity-X - initial API and implementation + * + */ + +package org.eclipse.edc.iam.identitytrust.transform; + +import org.eclipse.edc.jsonld.TitaniumJsonLd; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.jsonld.spi.JsonLdNamespace; +import org.eclipse.edc.junit.testfixtures.TestUtils; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; + +import java.util.stream.Stream; + +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DCP_CONTEXT_URL; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_0_8; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_1_0; +import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_V_1_0_CONTEXT; +import static org.mockito.Mockito.mock; + +public class TestContextProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) throws Exception { + return Stream.of( + Arguments.of(new TestContext(DCP_CONTEXT_URL, DSPACE_DCP_NAMESPACE_V_0_8, createJsonLd(DCP_CONTEXT_URL))), + Arguments.of(new TestContext(DSPACE_DCP_V_1_0_CONTEXT, DSPACE_DCP_NAMESPACE_V_1_0, createJsonLd(DSPACE_DCP_V_1_0_CONTEXT)))); + } + + private JsonLd createJsonLd(String activeContext) { + var jsonLd = new TitaniumJsonLd(mock()); + jsonLd.registerCachedDocument("https://identity.foundation/presentation-exchange/submission/v1", TestUtils.getFileFromResourceName("presentation_ex.json").toURI()); + jsonLd.registerCachedDocument(DCP_CONTEXT_URL, TestUtils.getFileFromResourceName("document/dcp.v08.jsonld").toURI()); + jsonLd.registerCachedDocument(DSPACE_DCP_V_1_0_CONTEXT, TestUtils.getFileFromResourceName("document/dcp.v1.0.jsonld").toURI()); + jsonLd.registerContext(activeContext); + return jsonLd; + } + + public record TestContext(String context, JsonLdNamespace namespace, JsonLd jsonLd) { + + public String toIri(String term) { + return namespace.toIri(term); + } + } +} diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformerTest.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformerTest.java new file mode 100644 index 00000000000..3121d527eda --- /dev/null +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationQueryTransformerTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025 Cofinity-X + * + * 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: + * Cofinity-X - initial API and implementation + * + */ + +package org.eclipse.edc.iam.identitytrust.transform.from; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.Json; +import org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage; +import org.eclipse.edc.iam.identitytrust.transform.TestContextProvider; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.presentationdefinition.PresentationDefinition; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_SCOPE_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_TERM; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class JsonObjectFromPresentationQueryTransformerTest { + + private final TransformerContext context = mock(); + private final ObjectMapper mapper = JacksonJsonLd.createObjectMapper(); + private final TypeManager typeManager = mock(); + + @BeforeEach + void setUp() { + when(typeManager.getMapper("test")).thenReturn(mapper); + } + + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform(TestContextProvider.TestContext ctx) { + + var transformer = new JsonObjectFromPresentationQueryTransformer(typeManager, "test", ctx.namespace()); + var response = PresentationQueryMessage.Builder.newinstance().scopes(List.of("scope")).build(); + + var json = transformer.transform(response, context); + + assertThat(json).isNotNull(); + assertThat(json.getJsonString(TYPE).getString()).isEqualTo(ctx.toIri(PRESENTATION_QUERY_MESSAGE_TERM)); + assertThat(json.getJsonArray(ctx.toIri(PRESENTATION_QUERY_MESSAGE_SCOPE_TERM))) + .hasSize(1) + .contains(Json.createValue("scope")); + + } + + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withPresentationDefinition(TestContextProvider.TestContext ctx) { + + var transformer = new JsonObjectFromPresentationQueryTransformer(typeManager, "test", ctx.namespace()); + var response = PresentationQueryMessage.Builder.newinstance() + .presentationDefinition(PresentationDefinition.Builder.newInstance() + .id("id") + .build()).build(); + + var json = transformer.transform(response, context); + + assertThat(json).isNotNull(); + assertThat(json.getJsonString(TYPE).getString()).isEqualTo(ctx.toIri(PRESENTATION_QUERY_MESSAGE_TERM)); + assertThat(json.getJsonObject(ctx.toIri(PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM))) + .isNotNull(); + + } +} diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformerTest.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformerTest.java index 6321e443972..528a36ad8f3 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformerTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/from/JsonObjectFromPresentationResponseMessageTransformerTest.java @@ -16,36 +16,38 @@ import jakarta.json.Json; import org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage; +import org.eclipse.edc.iam.identitytrust.transform.TestContextProvider; import org.eclipse.edc.transform.spi.TransformerContext; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY; -import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM; +import static org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage.PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; import static org.mockito.Mockito.mock; public class JsonObjectFromPresentationResponseMessageTransformerTest { - private final JsonObjectFromPresentationResponseMessageTransformer transformer = new JsonObjectFromPresentationResponseMessageTransformer(); - private final TransformerContext context = mock(); - @Test - void transform() { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform(TestContextProvider.TestContext ctx) { + var transformer = new JsonObjectFromPresentationResponseMessageTransformer(ctx.namespace()); var response = PresentationResponseMessage.Builder.newinstance().presentation(List.of("jwt")).build(); var json = transformer.transform(response, context); assertThat(json).isNotNull(); - assertThat(json.getJsonString(TYPE).getString()).isEqualTo(PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY); + assertThat(json.getJsonString(TYPE).getString()).isEqualTo(ctx.toIri(PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM)); - assertThat(json.getJsonObject(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY)) + assertThat(json.getJsonObject(ctx.toIri(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM))) .extracting(object -> object.get(VALUE).asJsonArray()) .satisfies(arr -> { assertThat(arr).hasSize(1) @@ -55,8 +57,11 @@ void transform() { } - @Test - void transform_withJson() { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withJson(TestContextProvider.TestContext ctx) { + var transformer = new JsonObjectFromPresentationResponseMessageTransformer(ctx.namespace()); + var response = PresentationResponseMessage.Builder.newinstance() .presentation(List.of(Map.of("@context", List.of()))) .build(); @@ -64,14 +69,14 @@ void transform_withJson() { var json = transformer.transform(response, context); assertThat(json).isNotNull(); - assertThat(json.getJsonString(TYPE).getString()).isEqualTo(PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY); + assertThat(json.getJsonString(TYPE).getString()).isEqualTo(ctx.toIri(PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM)); var expected = Json.createObjectBuilder() .add("@context", Json.createArrayBuilder().build()) .build(); - assertThat(json.getJsonObject(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY)) + assertThat(json.getJsonObject(ctx.toIri(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM))) .extracting(object -> object.get(VALUE).asJsonArray()) .satisfies(arr -> { assertThat(arr).hasSize(1) @@ -81,21 +86,24 @@ void transform_withJson() { } - @Test - void transform_withStringAndJson() { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withStringAndJson(TestContextProvider.TestContext ctx) { + var transformer = new JsonObjectFromPresentationResponseMessageTransformer(ctx.namespace()); + var response = PresentationResponseMessage.Builder.newinstance() .presentation(List.of("jwt", Map.of("@context", List.of()))) .build(); var json = transformer.transform(response, context); assertThat(json).isNotNull(); - assertThat(json.getJsonString(TYPE).getString()).isEqualTo(PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY); + assertThat(json.getJsonString(TYPE).getString()).isEqualTo(ctx.toIri(PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM)); var complex = Json.createObjectBuilder() .add("@context", Json.createArrayBuilder().build()) .build(); - assertThat(json.getJsonObject(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY)) + assertThat(json.getJsonObject(ctx.toIri(PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM))) .extracting(object -> object.get(VALUE).asJsonArray()) .satisfies(arr -> { assertThat(arr).hasSize(2).containsExactly(Json.createValue("jwt"), complex); diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/serde/PresentationResponseMessageSerdeTest.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/serde/PresentationResponseMessageSerdeTest.java index 6fa4706c113..ab7b7e887d7 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/serde/PresentationResponseMessageSerdeTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/serde/PresentationResponseMessageSerdeTest.java @@ -17,56 +17,48 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.JsonObject; +import org.eclipse.edc.iam.identitytrust.transform.TestContextProvider; import org.eclipse.edc.iam.identitytrust.transform.from.JsonObjectFromPresentationResponseMessageTransformer; import org.eclipse.edc.iam.identitytrust.transform.to.JsonObjectToPresentationResponseMessageTransformer; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.TransformerContextImpl; import org.eclipse.edc.transform.TypeTransformerRegistryImpl; import org.eclipse.edc.transform.spi.TransformerContext; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DCP_CONTEXT_URL; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class PresentationResponseMessageSerdeTest { - private final JsonLd jsonLd = new TitaniumJsonLd(mock()); private final ObjectMapper mapper = JacksonJsonLd.createObjectMapper(); private final TypeManager typeManager = mock(); private final TypeTransformerRegistry trr = new TypeTransformerRegistryImpl(); private final TransformerContext context = new TransformerContextImpl(trr); - private final JsonObjectFromPresentationResponseMessageTransformer fromTransformer = new JsonObjectFromPresentationResponseMessageTransformer(); - private final JsonObjectToPresentationResponseMessageTransformer toTransformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test"); + @BeforeEach void setUp() { - jsonLd.registerCachedDocument("https://identity.foundation/presentation-exchange/submission/v1", TestUtils.getFileFromResourceName("presentation_ex.json").toURI()); - jsonLd.registerCachedDocument(DCP_CONTEXT_URL, TestUtils.getFileFromResourceName("document/dcp.v08.jsonld").toURI()); - jsonLd.registerContext(DCP_CONTEXT_URL); - // delegate to the generic transformer - - trr.register(new JsonValueToGenericTypeTransformer(typeManager, "test")); when(typeManager.getMapper("test")).thenReturn(mapper); } - @Test - void serde() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void serde(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var fromTransformer = new JsonObjectFromPresentationResponseMessageTransformer(ctx.namespace()); + var toTransformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test", ctx.namespace()); var obj = """ { "@context": [ - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationResponseMessage", "presentation": [ @@ -81,17 +73,18 @@ void serde() throws JsonProcessingException { "jwtPresentation" ] } - """; + """ + .formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); var query = toTransformer.transform(jo.getContent(), context); assertThat(query).isNotNull(); var expandedJson = fromTransformer.transform(query, context); - var compacted = jsonLd.compact(expandedJson).getContent(); + var compacted = ctx.jsonLd().compact(expandedJson).getContent(); assertThat(json.getJsonArray("@context")).isEqualTo(compacted.getJsonArray("@context")); assertThat(json.getJsonArray("presentation")).isEqualTo(compacted.getJsonArray("presentation")); diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryMessageTransformerTest.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryMessageTransformerTest.java index 49671253183..b688f355512 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryMessageTransformerTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationQueryMessageTransformerTest.java @@ -17,10 +17,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.JsonObject; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.iam.identitytrust.transform.TestContextProvider; import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.TransformerContextImpl; import org.eclipse.edc.transform.TypeTransformerRegistryImpl; @@ -28,39 +26,37 @@ import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DCP_CONTEXT_URL; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class JsonObjectToPresentationQueryMessageTransformerTest { private final ObjectMapper mapper = JacksonJsonLd.createObjectMapper(); private final TypeManager typeManager = mock(); - private final JsonObjectToPresentationQueryTransformer transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test"); - private final JsonLd jsonLd = new TitaniumJsonLd(mock()); private final TypeTransformerRegistry trr = new TypeTransformerRegistryImpl(); private final TransformerContext context = new TransformerContextImpl(trr); @BeforeEach void setUp() { - jsonLd.registerCachedDocument("https://identity.foundation/presentation-exchange/submission/v1", TestUtils.getFileFromResourceName("presentation_ex.json").toURI()); - jsonLd.registerCachedDocument(DCP_CONTEXT_URL, TestUtils.getFileFromResourceName("document/dcp.v08.jsonld").toURI()); - // delegate to the generic transformer - trr.register(new JsonValueToGenericTypeTransformer(typeManager, "test")); when(typeManager.getMapper("test")).thenReturn(mapper); } - @Test - void transform_withScopes() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withScopes(TestContextProvider.TestContext ctx) throws JsonProcessingException { + + var transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ "https://identity.foundation/presentation-exchange/submission/v1", - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationQueryMessage", "scope": [ @@ -68,9 +64,9 @@ void transform_withScopes() throws JsonProcessingException { "org.eclipse.edc.vc.type:AnotherCredential:all" ] } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -83,20 +79,23 @@ void transform_withScopes() throws JsonProcessingException { } - @Test - void transform_withEmptyScopes() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withEmptyScopes(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ "https://identity.foundation/presentation-exchange/submission/v1", - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationQueryMessage", "scope": [] } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -105,19 +104,22 @@ void transform_withEmptyScopes() throws JsonProcessingException { assertThat(query.getPresentationDefinition()).isNull(); } - @Test - void transform_withNullScopes() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withNullScopes(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ "https://identity.foundation/presentation-exchange/submission/v1", - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationQueryMessage" } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -127,22 +129,25 @@ void transform_withNullScopes() throws JsonProcessingException { } - @Test - void transform_withScopes_separatedByWhitespace() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withScopes_separatedByWhitespace(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ "https://identity.foundation/presentation-exchange/submission/v1", - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationQueryMessage", "scope": [ "org.eclipse.edc.vc.type:TestCredential:read org.eclipse.edc.vc.type:AnotherCredential:all" ] } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -154,13 +159,15 @@ void transform_withScopes_separatedByWhitespace() throws JsonProcessingException assertThat(query.getPresentationDefinition()).isNull(); } - @Test - void transform_withPresentationDefinition() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withPresentationDefinition(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test", ctx.namespace()); var json = """ { "@context": [ "https://identity.foundation/presentation-exchange/submission/v1", - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationQueryMessage", "presentationDefinition": { @@ -187,10 +194,10 @@ void transform_withPresentationDefinition() throws JsonProcessingException { ] } } - """; + """.formatted(ctx.context()); var jobj = mapper.readValue(json, JsonObject.class); - var expansion = jsonLd.expand(jobj); + var expansion = ctx.jsonLd().expand(jobj); assertThat(expansion.succeeded()).withFailMessage(expansion::getFailureDetail).isTrue(); var query = transformer.transform(expansion.getContent(), context); @@ -202,13 +209,15 @@ void transform_withPresentationDefinition() throws JsonProcessingException { } - @Test - void transform_withScopesAndPresDef() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_withScopesAndPresDef(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationQueryTransformer(typeManager, "test", ctx.namespace()); var json = """ { "@context": [ "https://identity.foundation/presentation-exchange/submission/v1", - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationQueryMessage", "scope": ["test-scope1"], @@ -236,10 +245,10 @@ void transform_withScopesAndPresDef() throws JsonProcessingException { ] } } - """; + """.formatted(ctx.context()); var jobj = mapper.readValue(json, JsonObject.class); - var expansion = jsonLd.expand(jobj); + var expansion = ctx.jsonLd().expand(jobj); assertThat(expansion.succeeded()).withFailMessage(expansion::getFailureDetail).isTrue(); var query = transformer.transform(expansion.getContent(), context); diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformerTest.java b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformerTest.java index 830f1b4cce1..9e40618668b 100644 --- a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformerTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/java/org/eclipse/edc/iam/identitytrust/transform/to/JsonObjectToPresentationResponseMessageTransformerTest.java @@ -17,10 +17,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.JsonObject; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.iam.identitytrust.transform.TestContextProvider; import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.TransformerContextImpl; import org.eclipse.edc.transform.TypeTransformerRegistryImpl; @@ -28,46 +26,42 @@ import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DCP_CONTEXT_URL; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class JsonObjectToPresentationResponseMessageTransformerTest { private final ObjectMapper mapper = JacksonJsonLd.createObjectMapper(); private final TypeManager typeManager = mock(); - private final JsonObjectToPresentationResponseMessageTransformer transformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test"); - private final JsonLd jsonLd = new TitaniumJsonLd(mock()); private final TypeTransformerRegistry trr = new TypeTransformerRegistryImpl(); private final TransformerContext context = new TransformerContextImpl(trr); @BeforeEach void setUp() { - jsonLd.registerCachedDocument("https://identity.foundation/presentation-exchange/submission/v1", TestUtils.getFileFromResourceName("presentation_ex.json").toURI()); - jsonLd.registerCachedDocument(DCP_CONTEXT_URL, TestUtils.getFileFromResourceName("document/dcp.v08.jsonld").toURI()); - // delegate to the generic transformer - trr.register(new JsonValueToGenericTypeTransformer(typeManager, "test")); when(typeManager.getMapper("test")).thenReturn(mapper); } - @Test - void transform() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test", ctx.namespace()); var obj = """ { "@context": [ - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationResponseMessage", "presentation": "jwtPresentation" } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -77,19 +71,21 @@ void transform() throws JsonProcessingException { assertThat(query.getPresentationSubmission()).isNull(); } - @Test - void transform_MultipleJwt() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_MultipleJwt(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test", ctx.namespace()); var obj = """ { "@context": [ - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationResponseMessage", "presentation": ["firstJwtPresentation", "secondJwtPresentation"] } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -100,12 +96,15 @@ void transform_MultipleJwt() throws JsonProcessingException { } - @Test - void transform_singleJson() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_singleJson(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationResponseMessage", "presentation": { @@ -117,9 +116,9 @@ void transform_singleJson() throws JsonProcessingException { ] } } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -130,12 +129,15 @@ void transform_singleJson() throws JsonProcessingException { assertThat(query.getPresentationSubmission()).isNull(); } - @Test - void transform_multipleJson() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_multipleJson(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationResponseMessage", "presentation": [ @@ -157,9 +159,9 @@ void transform_multipleJson() throws JsonProcessingException { } ] } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); @@ -171,12 +173,15 @@ void transform_multipleJson() throws JsonProcessingException { assertThat(query.getPresentationSubmission()).isNull(); } - @Test - void transform_mixed() throws JsonProcessingException { + @ParameterizedTest + @ArgumentsSource(TestContextProvider.class) + void transform_mixed(TestContextProvider.TestContext ctx) throws JsonProcessingException { + var transformer = new JsonObjectToPresentationResponseMessageTransformer(typeManager, "test", ctx.namespace()); + var obj = """ { "@context": [ - "https://w3id.org/tractusx-trust/v0.8" + "%s" ], "@type": "PresentationResponseMessage", "presentation": [ @@ -191,9 +196,9 @@ void transform_mixed() throws JsonProcessingException { "jwtPresentation" ] } - """; + """.formatted(ctx.context()); var json = mapper.readValue(obj, JsonObject.class); - var jo = jsonLd.expand(json); + var jo = ctx.jsonLd().expand(json); assertThat(jo.succeeded()).withFailMessage(jo::getFailureDetail).isTrue(); var query = transformer.transform(jo.getContent(), context); diff --git a/extensions/common/iam/identity-trust/identity-trust-transform/src/test/resources/document/dcp.v1.0.jsonld b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/resources/document/dcp.v1.0.jsonld new file mode 100644 index 00000000000..f7858e3423d --- /dev/null +++ b/extensions/common/iam/identity-trust/identity-trust-transform/src/test/resources/document/dcp.v1.0.jsonld @@ -0,0 +1,137 @@ +{ + "@context": { + "@version": 1.1, + "@protected": true, + "dcp": "https://w3id.org/dspace-dcp/v1.0/", + "cred": "https://www.w3.org/2018/credentials/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "id": "@id", + "type": "@type", + "CredentialContainer": { + "@id": "dcp:CredentialContainer", + "@context": { + "payload": { + "@id": "dcp:payload", + "@type": "xsd:string" + } + } + }, + "CredentialMessage": { + "@id": "dcp:CredentialMessage", + "@context": { + "credentials": { + "@id": "dcp:credentials", + "@container": "@set" + }, + "requestId": { + "@id": "dcp:requestId", + "@type": "@id" + } + } + }, + "CredentialObject": { + "@id": "dcp:CredentialObject", + "@context": { + "credentialType": { + "@id": "dcp:credentialType", + "@container": "@set" + }, + "offerReason": { + "@id": "dcp:offerReason", + "@type": "xsd:string" + }, + "bindingMethods": { + "@id": "dcp:bindingMethods", + "@type": "xsd:string", + "@container": "@set" + }, + "profiles": { + "@id": "dcp:profiles", + "@type": "xsd:string", + "@container": "@set" + }, + "issuancePolicy": { + "@id": "dcp:issuancePolicy", + "@type": "@json" + } + } + }, + "CredentialOfferMessage": { + "@id": "dcp:CredentialOfferMessage", + "@context": { + "credentialIssuer": "cred:issuer", + "credentials": { + "@id": "dcp:credentials", + "@container": "@set" + } + } + }, + "CredentialRequestMessage": { + "@id": "dcp:CredentialRequestMessage", + "@context": { + "format": "dcp:format", + "credentialType": { + "@id": "dcp:credentialType", + "@type": "@vocab", + "@container": "@set" + } + } + }, + "CredentialService": "dcp:CredentialService", + "CredentialStatus": { + "@id": "dcp:CredentialStatus", + "@context": { + "requestId": { + "@id": "dcp:requestId", + "@type": "@id" + }, + "status": { + "@id": "dcp:status", + "@type": "@vocab" + }, + "RECEIVED": "dcp:RECEIVED", + "REJECTED": "dcp:REJECTED", + "ISSUED": "dcp:ISSUED" + } + }, + "IssuerMetadata": { + "@id": "dcp:IssuerMetadata", + "@context": { + "credentialIssuer": "cred:issuer", + "credentialsSupported": { + "@id": "dcp:credentialsSupported", + "@container": "@set" + } + } + }, + "IssuerService": "dcp:IssuerService", + "PresentationQueryMessage": { + "@id": "dcp:PresentationQueryMessage", + "@context": { + "presentationDefinition": { + "@id": "dcp:presentationDefinition", + "@type": "@json" + }, + "scope": { + "@id": "dcp:scope", + "@type": "xsd:string", + "@container": "@set" + } + } + }, + "PresentationResponseMessage": { + "@id": "dcp:PresentationResponseMessage", + "@context": { + "presentation": { + "@id": "dcp:presentation", + "@container": "@set", + "@type": "@json" + }, + "presentationSubmission": { + "@id": "dcp:presentationSubmission", + "@type": "@json" + } + } + } + } +} \ No newline at end of file diff --git a/spi/common/identity-trust-spi/build.gradle.kts b/spi/common/identity-trust-spi/build.gradle.kts index c548c889c54..5daa0e136bb 100644 --- a/spi/common/identity-trust-spi/build.gradle.kts +++ b/spi/common/identity-trust-spi/build.gradle.kts @@ -21,6 +21,7 @@ plugins { dependencies { api(project(":spi:common:core-spi")) api(project(":spi:common:token-spi")) + api(project(":spi:common:json-ld-spi")) api(project(":spi:common:participant-spi")) api(project(":spi:common:policy:request-policy-context-spi")) api(project(":spi:common:policy-engine-spi")) diff --git a/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/DcpConstants.java b/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/DcpConstants.java index 9d08b2d65f4..902177052f9 100644 --- a/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/DcpConstants.java +++ b/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/DcpConstants.java @@ -14,9 +14,17 @@ package org.eclipse.edc.iam.identitytrust.spi; -public interface DcpConstants { +import org.eclipse.edc.jsonld.spi.JsonLdNamespace; +public interface DcpConstants { + @Deprecated(since = "0.12.0") String DCP_CONTEXT_URL = "https://w3id.org/tractusx-trust/v0.8"; + @Deprecated(since = "0.12.0") String DCP_PREFIX = DCP_CONTEXT_URL + "/"; + @Deprecated(since = "0.12.0") + JsonLdNamespace DSPACE_DCP_NAMESPACE_V_0_8 = new JsonLdNamespace(DCP_PREFIX); + + String DSPACE_DCP_V_1_0_CONTEXT = "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"; + JsonLdNamespace DSPACE_DCP_NAMESPACE_V_1_0 = new JsonLdNamespace("https://w3id.org/dspace-dcp/v1.0/"); } diff --git a/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationQueryMessage.java b/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationQueryMessage.java index 1b36da02116..43fccb91fb9 100644 --- a/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationQueryMessage.java +++ b/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationQueryMessage.java @@ -29,10 +29,15 @@ * @see DCP Specification */ public class PresentationQueryMessage { + @Deprecated(since = "0.12.0", forRemoval = true) public static final String PRESENTATION_QUERY_MESSAGE_SCOPE_PROPERTY = DCP_PREFIX + "scope"; + public static final String PRESENTATION_QUERY_MESSAGE_SCOPE_TERM = "scope"; + @Deprecated(since = "0.12.0", forRemoval = true) public static final String PRESENTATION_QUERY_MESSAGE_DEFINITION_PROPERTY = DCP_PREFIX + "presentationDefinition"; - public static final String PRESENTATION_QUERY_MESSAGE_TYPE = "PresentationQueryMessage"; - public static final String PRESENTATION_QUERY_MESSAGE_TYPE_PROPERTY = DCP_PREFIX + PRESENTATION_QUERY_MESSAGE_TYPE; + public static final String PRESENTATION_QUERY_MESSAGE_DEFINITION_TERM = "presentationDefinition"; + public static final String PRESENTATION_QUERY_MESSAGE_TERM = "PresentationQueryMessage"; + @Deprecated(since = "0.12.0", forRemoval = true) + public static final String PRESENTATION_QUERY_MESSAGE_TYPE_PROPERTY = DCP_PREFIX + PRESENTATION_QUERY_MESSAGE_TERM; private final List scopes = new ArrayList<>(); private PresentationDefinition presentationDefinition; diff --git a/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationResponseMessage.java b/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationResponseMessage.java index 53fa69d38ae..87d9d4009db 100644 --- a/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationResponseMessage.java +++ b/spi/common/identity-trust-spi/src/main/java/org/eclipse/edc/iam/identitytrust/spi/model/PresentationResponseMessage.java @@ -31,9 +31,15 @@ */ public class PresentationResponseMessage { + @Deprecated(since = "0.12.0", forRemoval = true) public static final String PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_PROPERTY = DCP_PREFIX + "presentation"; + public static final String PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_TERM = "presentation"; + @Deprecated(since = "0.12.0", forRemoval = true) public static final String PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_SUBMISSION_PROPERTY = DCP_PREFIX + "presentationSubmission"; + public static final String PRESENTATION_RESPONSE_MESSAGE_PRESENTATION_SUBMISSION_TERM = "presentationSubmission"; + @Deprecated(since = "0.12.0", forRemoval = true) public static final String PRESENTATION_RESPONSE_MESSAGE_TYPE_PROPERTY = DCP_PREFIX + "PresentationResponseMessage"; + public static final String PRESENTATION_RESPONSE_MESSAGE_TYPE_TERM = "PresentationResponseMessage"; private List presentation = new ArrayList<>();