Skip to content

Commit

Permalink
Implement dummy endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ununhexium committed Jul 22, 2024
1 parent 1687477 commit 890fdf1
Show file tree
Hide file tree
Showing 27 changed files with 453 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus;
import de.sovity.edc.ext.catalog.crawler.utils.CrawlerDbAccess;
import de.sovity.edc.ext.catalog.crawler.utils.TestData;
import de.sovity.edc.extension.placeholderdatasource.PlaceholderDataSourceExtension;
import de.sovity.edc.extension.e2e.connector.config.ConnectorConfig;
import de.sovity.edc.extension.e2e.db.EdcRuntimeExtensionWithTestDatabase;
import de.sovity.edc.utils.jsonld.vocab.Prop;
Expand Down Expand Up @@ -104,6 +105,7 @@ class CrawlerE2eTest {
props.put(CrawlerExtension.CRON_DEAD_CONNECTOR_REFRESH, everySeconds);
props.put(CrawlerExtension.SCHEDULED_KILL_OFFLINE_CONNECTORS, everySeconds);
props.put(CrawlerExtension.KILL_OFFLINE_CONNECTORS_AFTER, "P1D");
props.put(PlaceholderDataSourceExtension.MY_EDC_DATASOURCE_PLACEHOLDER_BASEURL, "http://example.com/edc/backend");

return props;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package de.sovity.edc.ext.catalog.crawler;

import de.sovity.edc.extension.placeholderdatasource.PlaceholderEndpointService;
import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry;
import org.eclipse.edc.connector.spi.catalog.CatalogService;
import org.eclipse.edc.jsonld.spi.JsonLd;
Expand Down Expand Up @@ -90,6 +91,9 @@ public class CrawlerExtension implements ServiceExtension {
@Inject
private TypeManager typeManager;

@Inject
private PlaceholderEndpointService placeholderEndpointService;

@Inject
private ManagementApiTypeTransformerRegistry typeTransformerRegistry;

Expand Down Expand Up @@ -117,12 +121,13 @@ public void initialize(ServiceExtensionContext context) {
}

services = CrawlerExtensionContextBuilder.buildContext(
context.getConfig(),
context.getMonitor(),
typeManager,
typeTransformerRegistry,
jsonLd,
catalogService
context.getConfig(),
context.getMonitor(),
typeManager,
typeTransformerRegistry,
jsonLd,
catalogService,
placeholderEndpointService
);

// Provide access for the tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import de.sovity.edc.ext.wrapper.api.common.mappers.policy.LiteralMapper;
import de.sovity.edc.ext.wrapper.api.common.mappers.policy.OperatorMapper;
import de.sovity.edc.ext.wrapper.api.common.mappers.policy.PolicyValidator;
import de.sovity.edc.extension.placeholderdatasource.PlaceholderEndpointService;
import de.sovity.edc.utils.catalog.DspCatalogService;
import de.sovity.edc.utils.catalog.mapper.DspDataOfferBuilder;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -100,7 +101,8 @@ public static CrawlerExtensionContext buildContext(
TypeManager typeManager,
TypeTransformerRegistry typeTransformerRegistry,
JsonLd jsonLd,
CatalogService catalogService
CatalogService catalogService,
PlaceholderEndpointService placeholderEndpointService
) {
// Config
var crawlerConfigFactory = new CrawlerConfigFactory(config);
Expand All @@ -119,7 +121,7 @@ public static CrawlerExtensionContext buildContext(

// Services
var objectMapperJsonLd = getJsonLdObjectMapper(typeManager);
var assetMapper = newAssetMapper(typeTransformerRegistry, jsonLd);
var assetMapper = newAssetMapper(typeTransformerRegistry, jsonLd, placeholderEndpointService);
var policyMapper = newPolicyMapper(typeTransformerRegistry, objectMapperJsonLd);
var crawlerEventLogger = new CrawlerEventLogger();
var crawlerExecutionTimeLogger = new CrawlerExecutionTimeLogger();
Expand Down Expand Up @@ -226,7 +228,8 @@ private static PolicyMapper newPolicyMapper(TypeTransformerRegistry typeTransfor
@NotNull
private static AssetMapper newAssetMapper(
TypeTransformerRegistry typeTransformerRegistry,
JsonLd jsonLd
JsonLd jsonLd,
PlaceholderEndpointService placeholderEndpointService
) {
var edcPropertyUtils = new EdcPropertyUtils();
var assetJsonLdUtils = new AssetJsonLdUtils();
Expand All @@ -238,7 +241,7 @@ private static AssetMapper newAssetMapper(
endpoint -> false
);
var httpHeaderMapper = new HttpHeaderMapper();
var httpDataSourceMapper = new HttpDataSourceMapper(httpHeaderMapper);
var httpDataSourceMapper = new HttpDataSourceMapper(httpHeaderMapper, placeholderEndpointService);
var dataSourceMapper = new DataSourceMapper(
edcPropertyUtils,
httpDataSourceMapper
Expand Down
73 changes: 73 additions & 0 deletions extensions/placeholder-data-source/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!-- PROJECT LOGO -->
<br />
<div align="center">
<a href="https://github.com/sovity/edc-ce">
<img src="https://raw.githubusercontent.com/sovity/edc-ui/main/src/assets/images/sovity_logo.svg" alt="Logo" width="300">
</a>

<h3 align="center">EDC-Connector Extension:<br />Sovity Messenger</h3>

<p align="center">
<a href="https://github.com/sovity/edc-ce/issues/new?template=bug_report.md">Report Bug</a>
·
<a href="https://github.com/sovity/edc-ce/issues/new?template=feature_request.md">Request Feature</a>
</p>
</div>

## About this Extension

Provides a placeholder endpoint for on-request offers.

## Why does this extension exist?

This extension exists to inform the asset's consumer upon data retrieval that they should contact the provider and take extra steps to access the data.

## Configuration

`MY_EDC_DATASOURCE_PLACEHOLDER_BASEURL` / `my.edc.datasource.placeholder.baseurl` must be set to point to the placeholder endpoint's base URL.
`/data-source/placeholder/asset/` will be appended to this base URL to make it the placeholder data source endpoint. This will be the address as seen by the consumer.

---

On a production system, the base URL it could be:

`https://mycompany.com/path/to/backend`

with a placeholder value:

`https://mycompany.com/path/to/backend/data-source/placeholder/asset/`

and a full path to the asset's data:

`https://mycompany.com/path/to/backend/data-source/placeholder/asset?email=foo%40example.com&subject=Contact+us+now`.

---

On a system started with docker-compose, it will be pointing to the DSP port on the provider's EDC

`http://edc:11003/`

`http://edc:11003/data-source/placeholder/asset/`

`http://edc:11003/data-source/placeholder/asset?email=foo%40example.com&subject=Contact+us+now`

---

During local/dev/unit test execution, it will be pointing to the DSP port on the provider's EDC

`http://localhost:12345/`

where `12345` would be chosen at random

`http://localhost:12345/data-source/placeholder/asset/`

`http://localhost:12345/data-source/placeholder/asset?email=foo%40example.com&subject=Contact+us+now`

## License

Apache License 2.0 - see [LICENSE](../../LICENSE)

## Contact

sovity GmbH - [email protected]

30 changes: 30 additions & 0 deletions extensions/placeholder-data-source/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

plugins {
`java-library`
`maven-publish`
}

dependencies {
annotationProcessor(libs.lombok)
compileOnly(libs.lombok)

api(libs.edc.coreSpi)
api(libs.edc.controlPlaneSpi)
implementation(libs.edc.apiCore)
implementation(libs.edc.dspApiConfiguration)
implementation(libs.okhttp.okhttp)

testImplementation(libs.mockito.core)
testImplementation(libs.junit.api)
testRuntimeOnly(libs.junit.engine)
}

group = libs.versions.sovityEdcExtensionGroup.get()

publishing {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 sovity GmbH
*
* 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:
* sovity GmbH - initial API and implementation
*
*/

package de.sovity.edc.extension.placeholderdatasource;

import lombok.val;
import org.eclipse.edc.protocol.dsp.api.configuration.DspApiConfiguration;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provides;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.web.spi.WebService;

import static de.sovity.edc.extension.placeholderdatasource.PlaceholderDataSourceExtension.NAME;

@Extension(value = NAME)
@Provides(PlaceholderEndpointService.class)
public class PlaceholderDataSourceExtension implements ServiceExtension {

public static final String NAME = "Placeholder Data Source";

@Setting(required = true)
public static final String MY_EDC_DATASOURCE_PLACEHOLDER_BASEURL = "my.edc.datasource.placeholder.baseurl";

@Inject
private DspApiConfiguration dspApiConfiguration;

@Inject
private WebService webService;

@Override
public void initialize(ServiceExtensionContext context) {
val controller = new PlaceholderEndpointController();
webService.registerResource(dspApiConfiguration.getContextAlias(), controller);

val baseUrl = context.getConfig().getString(MY_EDC_DATASOURCE_PLACEHOLDER_BASEURL);
context.registerService(PlaceholderEndpointService.class, new PlaceholderEndpointService(baseUrl));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 sovity GmbH
*
* 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:
* sovity GmbH - initial API and implementation
*
*/

package de.sovity.edc.extension.placeholderdatasource;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Produces({MediaType.APPLICATION_JSON})
@Path("/data-source/placeholder")
public class PlaceholderEndpointController {

@GET
@Path("/{path:.*}")
@Produces(MediaType.TEXT_PLAIN)
@Consumes("*/*")
public Response get(@QueryParam("email") String email, @QueryParam("subject") String subject) {
return Response.ok("""
This is not a real data offer.
The offer you are trying to use only has this placeholder as a dummy endpoint and requires you top take extra actions to access it.
Please contact the data provider for more information about how to access it.
""" + "\n\n" + "Email: " + email + "\n" + "Subject: " + subject + "\n"
).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 sovity GmbH
*
* 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:
* sovity GmbH - initial API and implementation
*
*/

package de.sovity.edc.extension.placeholderdatasource;

import lombok.RequiredArgsConstructor;
import okhttp3.HttpUrl;

@RequiredArgsConstructor
public class PlaceholderEndpointService {

private final String baseUrl;

public static final String DUMMY_ENDPOINT_URL = "/data-source/placeholder/asset";

// TODO: maybe add String contactEmail, String contactPreferredEmailSubject and show them in the placeholder
public String getPlaceholderEndpointForAsset(String email, String subject) {
return HttpUrl.parse(baseUrl + DUMMY_ENDPOINT_URL)
.newBuilder()
.addQueryParameter("email", email)
.addQueryParameter("subject", subject)
.build()
.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
de.sovity.edc.extension.placeholderdatasource.PlaceholderDataSourceExtension
1 change: 1 addition & 0 deletions extensions/sovity-edc-extensions-package/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {

dependencies {
// Policies
api(project(":extensions:placeholder-data-source"))
api(project(":extensions:policy-referring-connector"))
api(project(":extensions:policy-time-interval"))
api(project(":extensions:policy-always-true"))
Expand Down
1 change: 1 addition & 0 deletions extensions/wrapper/wrapper-common-mappers/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies {
api(libs.edc.coreSpi)
api(libs.edc.transformCore)
api(libs.edc.transformSpi)
api(project(":extensions:placeholder-data-source"))
api(project(":extensions:wrapper:wrapper-common-api"))
api(project(":utils:json-and-jsonld-utils"))
implementation(libs.apache.commonsLang)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* sovity GmbH - initial API and implementation
*
*/

package de.sovity.edc.ext.wrapper.api.common.mappers;

import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdBuilder;
Expand Down Expand Up @@ -53,6 +53,8 @@ public Asset editAsset(
@NonNull UiAssetEditRequest editRequest
) {
var assetJsonLd = buildAssetJsonLd(asset);
// edit request is all empty
// assetJsonLd contains the manually set baseUrl
var editedJsonLd = assetJsonLdBuilder.editAssetJsonLd(assetJsonLd, editRequest);
return buildAsset(editedJsonLd);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public class AssetEditRequestMapper {
* @param editRequest {@link UiAssetEditRequest}
* @return {@link UiAssetCreateRequest}
*/
public UiAssetCreateRequest buildCreateRequest(@NonNull UiAssetEditRequest editRequest, @NonNull String assetId) {
public UiAssetCreateRequest buildCreateRequest(
@NonNull UiAssetEditRequest editRequest,
@NonNull String assetId
) {
var dataSource = editRequest.getDataSourceOverrideOrNull();
if (dataSource == null) {
dataSource = dummyDataSource();
Expand Down Expand Up @@ -73,6 +76,8 @@ public UiAssetCreateRequest buildCreateRequest(@NonNull UiAssetEditRequest editR
}

private UiDataSource dummyDataSource() {
return UiDataSource.builder().type(DataSourceType.CUSTOM).build();
return UiDataSource.builder()
.type(DataSourceType.CUSTOM)
.build();
}
}
Loading

0 comments on commit 890fdf1

Please sign in to comment.