Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduces optional JSON-LD context for management API #4470

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-context.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ on:
push:
branches: [ main ]
paths:
- 'extensions/common/api/management-api-json-ld-context/src/main/resources/document/**'
- 'extensions/common/json-ld/src/main/resources/document/**'

jobs:
build:
Expand All @@ -39,7 +39,7 @@ jobs:
- name: copy contexts into public folder
run: |
mkdir -p public/context
cp extensions/common/api/management-api-json-ld-context/src/main/resources/document/management-context-v1.jsonld public/context/
cp extensions/common/json-ld/src/main/resources/document/management-context-v1.jsonld public/context/
- name: deploy to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion DEPENDENCIES
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
maven/mavencentral/com.apicatalog/carbon-did/0.3.0, Apache-2.0, approved, clearlydefined

Check warning on line 1 in DEPENDENCIES

View workflow job for this annotation

GitHub Actions / Dependency-Check / Dash-Verify-Licenses

Restricted Dependencies found

Some dependencies are marked 'restricted' - please review them
maven/mavencentral/com.apicatalog/copper-multibase/0.5.0, Apache-2.0, approved, #14501
maven/mavencentral/com.apicatalog/copper-multicodec/0.1.1, Apache-2.0, approved, #14500
maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.14.0, Apache-2.0, approved, #14503
Expand Down Expand Up @@ -81,7 +81,7 @@
maven/mavencentral/com.lmax/disruptor/3.4.4, Apache-2.0, approved, clearlydefined
maven/mavencentral/com.networknt/json-schema-validator/1.0.76, Apache-2.0, approved, CQ22638
maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.28, Apache-2.0, approved, clearlydefined
maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.41.1, , restricted, clearlydefined
maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.41.1, Apache-2.0, approved, clearlydefined
maven/mavencentral/com.puppycrawl.tools/checkstyle/10.18.1, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #16060
maven/mavencentral/com.samskivert/jmustache/1.15, BSD-2-Clause AND BSD-3-Clause, approved, clearlydefined
maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class JsonLdConfiguration {

private boolean httpEnabled = false;
private boolean httpsEnabled = false;
private boolean avoidVocab = false;
private boolean checkPrefixes = true;

private JsonLdConfiguration() {
Expand All @@ -36,6 +37,10 @@ public boolean shouldCheckPrefixes() {
return checkPrefixes;
}

public boolean isAvoidVocab() {
return avoidVocab;
}

public static class Builder {

private final JsonLdConfiguration configuration = new JsonLdConfiguration();
Expand All @@ -54,6 +59,11 @@ public Builder httpsEnabled(boolean httpsEnabled) {
return this;
}

public Builder avoidVocab(boolean avoidVocab) {
configuration.avoidVocab = avoidVocab;
return this;
}

public Builder checkPrefixes(boolean checkPrefixes) {
configuration.checkPrefixes = checkPrefixes;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import static jakarta.json.Json.createBuilderFactory;
import static jakarta.json.Json.createObjectBuilder;
import static java.util.Optional.ofNullable;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;

/**
* Implementation of the {@link JsonLd} interface that uses the Titanium library for all JSON-LD operations.
Expand All @@ -66,6 +67,7 @@ public class TitaniumJsonLd implements JsonLd {
private final JsonObjectValidator validator;

private final boolean shouldCheckPrefixes;
private final boolean isVocabEnabled;

public TitaniumJsonLd(Monitor monitor) {
this(monitor, JsonLdConfiguration.Builder.newInstance().build());
Expand All @@ -75,6 +77,7 @@ public TitaniumJsonLd(Monitor monitor, JsonLdConfiguration configuration) {
this.monitor = monitor;
this.documentLoader = new CachedDocumentLoader(configuration, monitor);
this.shouldCheckPrefixes = configuration.shouldCheckPrefixes();
this.isVocabEnabled = configuration.isAvoidVocab();
this.validator = JsonObjectValidator.newValidator()
.verify((path) -> new MissingPrefixes(path, this::getAllPrefixes))
.build();
Expand Down Expand Up @@ -124,6 +127,10 @@ public Result<JsonObject> compact(JsonObject json, String scope) {

@Override
public void registerNamespace(String prefix, String contextIri, String scope) {
// skip the @vocab if it's not enabled
if (isVocabEnabled && VOCAB.equals(prefix)) {
return;
}
var namespaces = scopedNamespaces.computeIfAbsent(scope, k -> new LinkedHashMap<>());
namespaces.put(prefix, contextIri);
}
Expand All @@ -146,9 +153,9 @@ private JsonObject injectVocab(JsonObject json) {
if (json.get(JsonLdKeywords.CONTEXT) instanceof JsonObject) {
var contextObject = ofNullable(json.getJsonObject(JsonLdKeywords.CONTEXT)).orElseGet(() -> createObjectBuilder().build());
var contextBuilder = createObjectBuilder(contextObject);
if (!contextObject.containsKey(JsonLdKeywords.VOCAB)) {
if (!contextObject.containsKey(VOCAB)) {
var newContextObject = contextBuilder
.add(JsonLdKeywords.VOCAB, CoreConstants.EDC_NAMESPACE)
.add(VOCAB, CoreConstants.EDC_NAMESPACE)
.build();
jsonObjectBuilder.add(JsonLdKeywords.CONTEXT, newContextObject);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@

import static jakarta.json.Json.createArrayBuilder;
import static jakarta.json.Json.createObjectBuilder;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
import static org.mockito.Mockito.mock;

class TitaniumJsonLdTest {
Expand Down Expand Up @@ -147,6 +149,34 @@ void compact() {
});
}

@Test
void compact_withVocab() {
var expanded = Json.createObjectBuilder()
.add(EDC_NAMESPACE + "item", "test")
.build();
var jsonLd = defaultService();
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE);
var compacted = jsonLd.compact(expanded);

assertThat(compacted).isSucceeded().satisfies(c -> {
Assertions.assertThat(c.getString("item")).isEqualTo("test");
});
}

@Test
void compact_withVocabDisabled() {
var expanded = Json.createObjectBuilder()
.add(EDC_NAMESPACE + "item", "test")
.build();
var jsonLd = defaultService(JsonLdConfiguration.Builder.newInstance().avoidVocab(true).build());
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE);
var compacted = jsonLd.compact(expanded);

assertThat(compacted).isSucceeded().satisfies(c -> {
Assertions.assertThat(c.getString(EDC_NAMESPACE + "item")).isEqualTo("test");
});
}

@Test
void compact_withCustomPrefix() {
var ns = "https://test.org/schema/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.Map;

import static java.lang.String.format;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCAT_PREFIX;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCAT_SCHEMA;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCT_PREFIX;
Expand All @@ -61,6 +62,8 @@
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX;
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;

/**
Expand Down Expand Up @@ -122,6 +125,9 @@ public void initialize(ServiceExtensionContext context) {
jsonLd.registerNamespace(DCT_PREFIX, DCT_SCHEMA, DSP_SCOPE);
jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, DSP_SCOPE);
jsonLd.registerNamespace(DSPACE_PREFIX, DSPACE_SCHEMA, DSP_SCOPE);
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, DSP_SCOPE);
jsonLd.registerNamespace(EDC_PREFIX, EDC_NAMESPACE, DSP_SCOPE);


webService.registerResource(ApiContext.PROTOCOL, new ObjectMapperProvider(jsonLdMapper));
webService.registerResource(ApiContext.PROTOCOL, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.eclipse.edc.protocol.dsp.http.api.configuration;

import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
import org.eclipse.edc.spi.system.Hostname;
Expand All @@ -36,8 +37,18 @@
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCAT_PREFIX;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCAT_SCHEMA;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCT_PREFIX;
import static org.eclipse.edc.jsonld.spi.Namespaces.DCT_SCHEMA;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.DSP_CALLBACK_ADDRESS;
import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.SETTINGS;
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
Expand All @@ -52,6 +63,8 @@ class DspApiConfigurationExtensionTest {
private final WebServer webServer = mock();
private final WebService webService = mock();
private final TypeManager typeManager = mock();
private final JsonLd jsonLd = mock();


@BeforeEach
void setUp(ServiceExtensionContext context) {
Expand All @@ -60,6 +73,7 @@ void setUp(ServiceExtensionContext context) {
context.registerService(WebServiceConfigurer.class, configurer);
context.registerService(TypeManager.class, typeManager);
context.registerService(Hostname.class, () -> "hostname");
context.registerService(JsonLd.class, jsonLd);
TypeTransformerRegistry typeTransformerRegistry = mock();
when(typeTransformerRegistry.forContext(any())).thenReturn(mock());
context.registerService(TypeTransformerRegistry.class, typeTransformerRegistry);
Expand Down Expand Up @@ -105,4 +119,16 @@ void initialize_shouldRegisterWebServiceProviders(DspApiConfigurationExtension e
verify(webService).registerResource(eq(ApiContext.PROTOCOL), isA(JerseyJsonLdInterceptor.class));
}

@Test
void initialize_shouldRegisterNamespaces(DspApiConfigurationExtension extension, ServiceExtensionContext context) {
extension.initialize(context);

verify(jsonLd).registerNamespace(DCAT_PREFIX, DCAT_SCHEMA, DSP_SCOPE);
verify(jsonLd).registerNamespace(DCT_PREFIX, DCT_SCHEMA, DSP_SCOPE);
verify(jsonLd).registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, DSP_SCOPE);
verify(jsonLd).registerNamespace(VOCAB, EDC_NAMESPACE, DSP_SCOPE);
verify(jsonLd).registerNamespace(EDC_PREFIX, EDC_NAMESPACE, DSP_SCOPE);
verify(jsonLd).registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, DSP_SCOPE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,13 @@
import java.util.stream.Stream;

import static java.lang.String.format;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_PREFIX;
import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_SCHEMA;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX;
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;

/**
Expand All @@ -63,12 +66,10 @@ public class ControlApiConfigurationExtension implements ServiceExtension {

@Setting(value = "Configures endpoint for reaching the Control API. If it's missing it defaults to the hostname configuration.")
public static final String CONTROL_API_ENDPOINT = "edc.control.endpoint";

public static final String CONTROL_SCOPE = "CONTROL_API";
private static final String WEB_SERVICE_NAME = "Control API";

@SettingContext("Control API context setting key")
private static final String CONTROL_CONFIG_KEY = "web.http." + ApiContext.CONTROL;

public static final WebServiceSettings SETTINGS = WebServiceSettings.Builder.newInstance()
.apiConfigKey(CONTROL_CONFIG_KEY)
.contextAlias(ApiContext.CONTROL)
Expand All @@ -77,7 +78,6 @@ public class ControlApiConfigurationExtension implements ServiceExtension {
.useDefaultContext(true)
.name(WEB_SERVICE_NAME)
.build();
private static final String CONTROL_SCOPE = "CONTROL_API";
private static final String API_VERSION_JSON_FILE = "control-api-version.json";

@Inject
Expand Down Expand Up @@ -110,6 +110,8 @@ public void initialize(ServiceExtensionContext context) {
var jsonLdMapper = typeManager.getMapper(JSON_LD);
context.registerService(ControlApiUrl.class, controlApiUrl(context, controlApiConfiguration));

jsonLd.registerNamespace(EDC_PREFIX, EDC_NAMESPACE, CONTROL_SCOPE);
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, CONTROL_SCOPE);
jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, CONTROL_SCOPE);
jsonLd.registerNamespace(DSPACE_PREFIX, DSPACE_SCHEMA, CONTROL_SCOPE);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.edc.api.auth.spi.AuthenticationRequestFilter;
import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.system.Hostname;
Expand All @@ -33,6 +34,14 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.CONTROL_API_ENDPOINT;
import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.CONTROL_SCOPE;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_PREFIX;
import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_SCHEMA;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
Expand All @@ -45,6 +54,7 @@ public class ControlApiConfigurationExtensionTest {

private final WebServiceConfigurer configurator = mock();
private final WebService webService = mock();
private final JsonLd jsonLd = mock();

private final WebServiceConfiguration webServiceConfiguration = WebServiceConfiguration.Builder.newInstance()
.path("/path")
Expand All @@ -57,6 +67,7 @@ void setUp(ServiceExtensionContext context) {
context.registerService(Hostname.class, () -> "hostname");
context.registerService(WebService.class, webService);
context.registerService(TypeManager.class, new JacksonTypeManager());
context.registerService(JsonLd.class, jsonLd);

when(configurator.configure(any(), any(), any())).thenReturn(webServiceConfiguration);
}
Expand Down Expand Up @@ -98,4 +109,14 @@ void shouldRegisterAuthenticationFilter(ControlApiConfigurationExtension extensi

verify(webService).registerResource(any(), isA(AuthenticationRequestFilter.class));
}

@Test
void shouldRegisterNamespaces(ControlApiConfigurationExtension extension, ServiceExtensionContext context) {
extension.initialize(context);

jsonLd.registerNamespace(EDC_PREFIX, EDC_NAMESPACE, CONTROL_SCOPE);
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, CONTROL_SCOPE);
jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, CONTROL_SCOPE);
jsonLd.registerNamespace(DSPACE_PREFIX, DSPACE_SCHEMA, CONTROL_SCOPE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@
import java.util.stream.Stream;

import static java.lang.String.format;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_CONNECTOR_MANAGEMENT_CONTEXT;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX;
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;

/**
Expand All @@ -75,10 +79,10 @@ public class ManagementApiConfigurationExtension implements ServiceExtension {
public static final String API_VERSION_JSON_FILE = "management-api-version.json";
public static final String NAME = "Management API configuration";
public static final String WEB_SERVICE_NAME = "Management API";
public static final String MANAGEMENT_SCOPE = "MANAGEMENT_API";

@SettingContext("Management API context setting key")
private static final String MANAGEMENT_CONFIG_KEY = "web.http." + ApiContext.MANAGEMENT;

public static final WebServiceSettings SETTINGS = WebServiceSettings.Builder.newInstance()
.apiConfigKey(MANAGEMENT_CONFIG_KEY)
.contextAlias(ApiContext.MANAGEMENT)
Expand All @@ -87,11 +91,14 @@ public class ManagementApiConfigurationExtension implements ServiceExtension {
.useDefaultContext(true)
.name(WEB_SERVICE_NAME)
.build();
private static final String MANAGEMENT_SCOPE = "MANAGEMENT_API";

@Setting(value = "Configures endpoint for reaching the Management API.", defaultValue = "<hostname:management.port/management.path>")
private static final String MANAGEMENT_API_ENDPOINT = "edc.management.endpoint";

private static final boolean DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT = false;

@Setting(value = "If set enable the usage of management api JSON-LD context.", defaultValue = "" + DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT)
private static final String MANAGEMENT_API_ENABLE_CONTEXT = "edc.management.context.enabled";

@Inject
private WebService webService;
@Inject
Expand Down Expand Up @@ -129,7 +136,16 @@ public void initialize(ServiceExtensionContext context) {
var authenticationFilter = new AuthenticationRequestFilter(authenticationRegistry, "management-api");
webService.registerResource(ApiContext.MANAGEMENT, authenticationFilter);

jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, MANAGEMENT_SCOPE);
var isManagementContextEnabled = context.getSetting(MANAGEMENT_API_ENABLE_CONTEXT, DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT);

if (isManagementContextEnabled) {
jsonLd.registerContext(EDC_CONNECTOR_MANAGEMENT_CONTEXT, MANAGEMENT_SCOPE);
} else {
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, MANAGEMENT_SCOPE);
jsonLd.registerNamespace(EDC_PREFIX, EDC_NAMESPACE, MANAGEMENT_SCOPE);
jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, MANAGEMENT_SCOPE);
}

var jsonLdMapper = typeManager.getMapper(JSON_LD);
webService.registerResource(ApiContext.MANAGEMENT, new ObjectMapperProvider(jsonLdMapper));
webService.registerResource(ApiContext.MANAGEMENT, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, MANAGEMENT_SCOPE));
Expand Down
Loading
Loading