Skip to content
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
3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ plugins {
}

group = "org.eclipse.dataplane-core"
version = "0.0.6-SNAPSHOT"
version = "0.0.7-SNAPSHOT"

repositories {
mavenCentral()
}

dependencies {
implementation("com.fasterxml.jackson.core:jackson-databind:2.21.1")
implementation("com.nimbusds:nimbus-jose-jwt:10.8")
implementation("jakarta.ws.rs:jakarta.ws.rs-api:4.0.0")

testImplementation(platform("org.junit:junit-bom:6.0.3"))
Expand Down
21 changes: 10 additions & 11 deletions src/main/java/org/eclipse/dataplane/Dataplane.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.eclipse.dataplane.domain.dataflow.DataFlowSuspendMessage;
import org.eclipse.dataplane.domain.dataflow.DataFlowTerminateMessage;
import org.eclipse.dataplane.domain.registration.Authorization;
import org.eclipse.dataplane.domain.registration.AuthorizationType;
import org.eclipse.dataplane.domain.registration.ControlPlaneRegistrationMessage;
import org.eclipse.dataplane.domain.registration.DataPlaneRegistrationMessage;
import org.eclipse.dataplane.logic.OnCompleted;
Expand Down Expand Up @@ -56,7 +55,6 @@
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiConsumer;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import static java.util.Collections.emptyMap;
Expand All @@ -79,7 +77,7 @@ public class Dataplane {
private OnCompleted onCompleted = dataFlow -> Result.failure(new UnsupportedOperationException("onCompleted is not implemented"));

private final HttpClient httpClient = HttpClient.newHttpClient();
private final Map<String, AuthorizationType> authorizationTypes = new HashMap<>();
private final Map<String, Authorization> authorizations = new HashMap<>();

public static Builder newInstance() {
return new Builder();
Expand Down Expand Up @@ -314,11 +312,10 @@ private Result<Void> notifyControlPlane(String action, DataFlow dataFlow, Object

var controlPlane = controlPlaneStore.findByEndpoint(dataFlow.getCallbackAddress());
if (controlPlane.succeeded()) {
var authorization = controlPlane.getContent().authorization();
if (authorization != null) {
var authorizationType = authorizationTypes.get(authorization.getType());
var castAuthorization = objectMapper.convertValue(authorization, authorizationType.authorizationClass());
authorizationType.authorizationFunction().accept(requestBuilder, castAuthorization);
var authorizationProfile = controlPlane.getContent().authorization();
if (authorizationProfile != null) {
var authorization = authorizations.get(authorizationProfile.getType());
authorization.apply(requestBuilder, authorizationProfile);
}
}

Expand Down Expand Up @@ -348,7 +345,7 @@ public ControlPlaneStore controlPlaneStore() {

public Result<Void> registerControlPlane(ControlPlaneRegistrationMessage message) {
for (var auth : message.authorization()) {
if (!authorizationTypes.containsKey(auth.getType())) {
if (!authorizations.containsKey(auth.getType())) {
return Result.failure(new AuthorizationNotSupported(auth));
}
}
Expand All @@ -371,12 +368,14 @@ public static class Builder {
private final Dataplane dataplane = new Dataplane();

private Builder() {

}

public Dataplane build() {
if (dataplane.id == null) {
dataplane.id = UUID.randomUUID().toString();
}

return dataplane;
}

Expand Down Expand Up @@ -430,8 +429,8 @@ public Builder onTerminate(OnTerminate onTerminate) {
return this;
}

public <T extends Authorization> Builder registerAuthorization(String type, Class<T> authorizationClass, BiConsumer<HttpRequest.Builder, T> authorizationFunction) {
dataplane.authorizationTypes.put(type, new AuthorizationType<>(type, authorizationClass, authorizationFunction));
public Builder registerAuthorization(Authorization authorization) {
dataplane.authorizations.put(authorization.type(), authorization);
return this;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
package org.eclipse.dataplane.domain.controlplane;

import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import org.eclipse.dataplane.domain.registration.Authorization;
import org.eclipse.dataplane.domain.registration.RawAuthorization;
import org.eclipse.dataplane.domain.registration.AuthorizationProfile;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -26,7 +25,7 @@ public class ControlPlane {

private String id;
private String endpoint;
private final List<RawAuthorization> authorizations = new ArrayList<>();
private final List<AuthorizationProfile> authorizations = new ArrayList<>();

public String getId() {
return id;
Expand All @@ -40,11 +39,11 @@ public static ControlPlane.Builder newInstance() {
return new ControlPlane.Builder();
}

public List<RawAuthorization> getAuthorizations() {
public List<AuthorizationProfile> getAuthorizations() {
return authorizations;
}

public Authorization authorization() {
public AuthorizationProfile authorization() {
return getAuthorizations().stream().findAny().orElse(null);
}

Expand Down Expand Up @@ -72,7 +71,7 @@ public Builder endpoint(String endpoint) {
return this;
}

public Builder authorization(List<RawAuthorization> authorizations) {
public Builder authorization(List<AuthorizationProfile> authorizations) {
controlPlane.authorizations.addAll(authorizations);
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,22 @@

package org.eclipse.dataplane.domain.registration;

import java.net.http.HttpRequest;

/**
* Defines structure for an authorization profile.
*/
public interface Authorization {

String getType();
/**
* Return the authorization profile type string
*/
String type();

/**
* Function that applies the authorization profile to the request builder.
* e.g. the Authorization header could be added with proper content.
*/
HttpRequest.Builder apply(HttpRequest.Builder requestBuilder, AuthorizationProfile profile);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2026 Think-it 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:
* Think-it GmbH - initial API and implementation
*
*/

package org.eclipse.dataplane.domain.registration;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import org.eclipse.dataplane.port.exception.IllegalAttributeTypeException;

import java.util.HashMap;
import java.util.Map;

public class AuthorizationProfile {

private final Map<String, Object> attributes;

public AuthorizationProfile() {
attributes = new HashMap<>();
}

public AuthorizationProfile(String type) {
this();
attributes.put("type", type);
}

public String getType() {
return attributes.get("type").toString();
}

@JsonAnyGetter
public Map<String, Object> getAttributes() {
return attributes;
}

@JsonAnySetter
public void setAttribute(String key, Object value) {
attributes.put(key, value);
}

public String stringAttribute(String key) {
var attribute = attributes.get(key);
if (attribute == null) {
return null;
}

if (attribute instanceof String stringAttribute) {
return stringAttribute;
}

throw new IllegalAttributeTypeException("Attribute %s is not a String but it's a %s".formatted(key, attribute.getClass().getSimpleName()));
}

public AuthorizationProfile withAttribute(String key, String value) {
setAttribute(key, value);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
public record ControlPlaneRegistrationMessage(
String controlplaneId,
String endpoint,
List<RawAuthorization> authorization
List<AuthorizationProfile> authorization
) {
public ControlPlaneRegistrationMessage(String controlplaneId, String endpoint) {
this(controlplaneId, endpoint, emptyList());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2026 Think-it 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:
* Think-it GmbH - initial API and implementation
*
*/

package org.eclipse.dataplane.domain.registration;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;

import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;
import static jakarta.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;

public class Oauth2ClientCredentialsAuthorization implements Authorization {

private final HttpClient httpClient = HttpClient.newHttpClient();
private final ObjectMapper objectMapper = new ObjectMapper();

@Override
public String type() {
return "oauth2_client_credentials";
}

@Override
public HttpRequest.Builder apply(HttpRequest.Builder requestBuilder, AuthorizationProfile profile) {
var tokenEndpoint = profile.stringAttribute("tokenEndpoint");

var parameters = Map.of(
"grant_type", "client_credentials",
"client_id", profile.stringAttribute("clientId"),
"client_secret", profile.stringAttribute("clientSecret")
);

var form = parameters.entrySet()
.stream()
.map(e -> e.getKey() + "=" + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
.collect(Collectors.joining("&"));


var request = HttpRequest.newBuilder(URI.create(tokenEndpoint))
.POST(HttpRequest.BodyPublishers.ofString(form))
.header("Content-Type", APPLICATION_FORM_URLENCODED)
.build();

try {
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var body = response.body();
var accessToken = objectMapper.readValue(body, Map.class).get("access_token").toString();
return requestBuilder.header(AUTHORIZATION, "Bearer " + accessToken);
} catch (Exception e) {
throw new RuntimeException(e);
}

}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@

package org.eclipse.dataplane.port.exception;

import org.eclipse.dataplane.domain.registration.Authorization;
import org.eclipse.dataplane.domain.registration.AuthorizationProfile;

public class AuthorizationNotSupported extends Exception {

public AuthorizationNotSupported(Authorization authorization) {
super("Authorization type " + authorization.getType() + " not supported");
public AuthorizationNotSupported(AuthorizationProfile authorizationProfile) {
super("Authorization type " + authorizationProfile.getType() + " not supported");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,10 @@
*
*/

package org.eclipse.dataplane.domain.registration;

import java.net.http.HttpRequest;
import java.util.function.BiConsumer;

public record AuthorizationType<T extends Authorization>(
String type,
Class<T> authorizationClass,
BiConsumer<HttpRequest.Builder, T> authorizationFunction // TODO: dedicated interface
) {
package org.eclipse.dataplane.port.exception;

public class IllegalAttributeTypeException extends RuntimeException {
public IllegalAttributeTypeException(String message) {
super(message);
}
}
Loading