Skip to content

Commit 4dc368f

Browse files
authored
feat: participant context config api (#64)
* feat: participant context config api * chore: update copyright
1 parent f708f6f commit 4dc368f

File tree

17 files changed

+802
-28
lines changed

17 files changed

+802
-28
lines changed

extensions/control-plane/api/management-api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ dependencies {
2626
api(project(":extensions:control-plane:api:management-api:contract-negotiation-api"))
2727
api(project(":extensions:control-plane:api:management-api:transfer-process-api"))
2828
api(project(":extensions:control-plane:api:management-api:participant-context-api"))
29+
api(project(":extensions:control-plane:api:management-api:participant-context-config-api"))
2930
api(project(":extensions:control-plane:api:management-api:management-api-configuration"))
3031
}

extensions/control-plane/api/management-api/participant-context-api/src/main/java/org/eclipse/edc/virtualized/connector/controlplane/api/management/participantcontext/v4/ParticipantContextApiV4.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Metaform Systems, Inc.
2+
* Copyright (c) 2025 Metaform Systems, Inc.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Apache License, Version 2.0 which is available at

extensions/control-plane/api/management-api/participant-context-api/src/main/java/org/eclipse/edc/virtualized/connector/controlplane/api/management/participantcontext/v4/ParticipantContextApiV4Controller.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Metaform Systems, Inc.
2+
* Copyright (c) 2025 Metaform Systems, Inc.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Apache License, Version 2.0 which is available at
@@ -18,21 +18,22 @@
1818
import jakarta.annotation.security.RolesAllowed;
1919
import jakarta.json.JsonArray;
2020
import jakarta.json.JsonObject;
21+
import jakarta.ws.rs.Consumes;
2122
import jakarta.ws.rs.DELETE;
2223
import jakarta.ws.rs.DefaultValue;
2324
import jakarta.ws.rs.GET;
2425
import jakarta.ws.rs.POST;
2526
import jakarta.ws.rs.PUT;
2627
import jakarta.ws.rs.Path;
2728
import jakarta.ws.rs.PathParam;
29+
import jakarta.ws.rs.Produces;
2830
import jakarta.ws.rs.QueryParam;
2931
import jakarta.ws.rs.core.Context;
3032
import jakarta.ws.rs.core.SecurityContext;
3133
import org.eclipse.edc.api.auth.spi.AuthorizationService;
3234
import org.eclipse.edc.api.auth.spi.ParticipantPrincipal;
3335
import org.eclipse.edc.api.auth.spi.RequiredScope;
3436
import org.eclipse.edc.api.model.IdResponse;
35-
import org.eclipse.edc.connector.controlplane.policy.spi.PolicyDefinition;
3637
import org.eclipse.edc.participantcontext.spi.service.ParticipantContextService;
3738
import org.eclipse.edc.participantcontext.spi.types.ParticipantContext;
3839
import org.eclipse.edc.spi.EdcException;
@@ -45,9 +46,12 @@
4546
import org.eclipse.edc.web.spi.validation.SchemaType;
4647

4748
import static jakarta.json.stream.JsonCollectors.toJsonArray;
49+
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
4850
import static org.eclipse.edc.participantcontext.spi.types.ParticipantContext.PARTICIPANT_CONTEXT_TYPE_TERM;
4951
import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper;
5052

53+
@Consumes(APPLICATION_JSON)
54+
@Produces(APPLICATION_JSON)
5155
@Path("/v4alpha/participants")
5256
public class ParticipantContextApiV4Controller implements ParticipantContextApiV4 {
5357

@@ -74,7 +78,7 @@ public JsonObject createParticipantV4(@SchemaType(PARTICIPANT_CONTEXT_TYPE_TERM)
7478
.orElseThrow(InvalidRequestException::new);
7579

7680
var created = participantContextService.createParticipantContext(participantContext)
77-
.orElseThrow(exceptionMapper(PolicyDefinition.class, participantContext.getParticipantContextId()));
81+
.orElseThrow(exceptionMapper(ParticipantContext.class, participantContext.getParticipantContextId()));
7882

7983
var responseDto = IdResponse.Builder.newInstance()
8084
.id(created.getParticipantContextId())
@@ -112,7 +116,7 @@ public void updateParticipantV4(@PathParam("id") String id, @SchemaType(PARTICIP
112116
.orElseThrow(exceptionMapper(ParticipantContext.class, id));
113117

114118
}
115-
119+
116120
@DELETE
117121
@Path("{id}")
118122
@RolesAllowed({ParticipantPrincipal.ROLE_PROVISIONER})

extensions/control-plane/api/management-api/participant-context-api/src/test/java/org/eclipse/edc/virtualized/connector/controlplane/api/management/participantcontext/ParticipantContextApiControllerTestBase.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2+
* Copyright (c) 2025 Metaform Systems, Inc.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Apache License, Version 2.0 which is available at
@@ -8,7 +8,7 @@
88
* SPDX-License-Identifier: Apache-2.0
99
*
1010
* Contributors:
11-
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
11+
* Metaform Systems, Inc. - initial API and implementation
1212
*
1313
*/
1414

@@ -90,7 +90,7 @@ private ParticipantContext createParticipantContext() {
9090
private ParticipantContext.Builder createParticipantContextBuilder() {
9191
return ParticipantContext.Builder.newInstance();
9292
}
93-
93+
9494
@Nested
9595
class FindById {
9696
@Test
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2025 Metaform Systems, Inc.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Metaform Systems, Inc. - initial API and implementation
12+
*
13+
*/
14+
15+
16+
17+
plugins {
18+
`java-library`
19+
id(libs.plugins.swagger.get().pluginId)
20+
21+
}
22+
23+
dependencies {
24+
25+
api(project(":spi:v-auth-spi"))
26+
implementation(libs.edc.spi.core)
27+
implementation(libs.edc.spi.contract)
28+
implementation(libs.edc.spi.controlplane)
29+
implementation(libs.edc.spi.participantcontext.config)
30+
implementation(libs.edc.spi.asset)
31+
implementation(libs.edc.spi.validator)
32+
implementation(libs.edc.spi.web)
33+
implementation(libs.edc.spi.transform)
34+
implementation(libs.edc.lib.controlplane.transform)
35+
implementation(libs.jakarta.annotation)
36+
37+
implementation(libs.edc.lib.api)
38+
implementation(libs.edc.lib.jersey.providers)
39+
implementation(libs.edc.lib.mgmtapi)
40+
implementation(libs.edc.lib.validator)
41+
42+
testImplementation(testFixtures(libs.edc.core.jersey))
43+
testImplementation(libs.restAssured)
44+
testImplementation(libs.awaitility)
45+
}
46+
47+
edcBuild {
48+
swagger {
49+
apiGroup.set("management-api")
50+
}
51+
}
52+
53+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2025 Metaform Systems, Inc.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Metaform Systems, Inc. - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.virtualized.connector.controlplane.api.management.participantcontext.config;
16+
17+
import jakarta.json.Json;
18+
import org.eclipse.edc.api.management.schema.ManagementApiJsonSchema;
19+
import org.eclipse.edc.connector.controlplane.transform.edc.participantcontext.config.from.JsonObjectFromParticipantContextConfigurationTransformer;
20+
import org.eclipse.edc.connector.controlplane.transform.edc.participantcontext.config.to.JsonObjectToParticipantContextConfigurationTransformer;
21+
import org.eclipse.edc.jsonld.spi.JsonLd;
22+
import org.eclipse.edc.participantcontext.spi.config.service.ParticipantContextConfigService;
23+
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
24+
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
25+
import org.eclipse.edc.spi.system.ServiceExtension;
26+
import org.eclipse.edc.spi.system.ServiceExtensionContext;
27+
import org.eclipse.edc.spi.types.TypeManager;
28+
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
29+
import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry;
30+
import org.eclipse.edc.virtualized.connector.controlplane.api.management.participantcontext.config.v4.ParticipantContextConfigApiV4Controller;
31+
import org.eclipse.edc.web.jersey.providers.jsonld.JerseyJsonLdInterceptor;
32+
import org.eclipse.edc.web.spi.WebService;
33+
import org.eclipse.edc.web.spi.configuration.ApiContext;
34+
35+
import java.util.Map;
36+
37+
import static org.eclipse.edc.api.management.ManagementApi.MANAGEMENT_SCOPE_V4;
38+
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;
39+
import static org.eclipse.edc.virtualized.connector.controlplane.api.management.participantcontext.config.ParticipantContextConfigManagementApiExtension.NAME;
40+
41+
@Extension(value = NAME)
42+
public class ParticipantContextConfigManagementApiExtension implements ServiceExtension {
43+
44+
public static final String NAME = "ParticipantContext config management API Extension";
45+
46+
@Inject
47+
private WebService webService;
48+
49+
@Inject
50+
private TypeTransformerRegistry transformerRegistry;
51+
52+
@Inject
53+
private JsonObjectValidatorRegistry validatorRegistry;
54+
55+
@Inject
56+
private JsonLd jsonLd;
57+
58+
@Inject
59+
private TypeManager typeManager;
60+
61+
@Inject
62+
private ParticipantContextConfigService configService;
63+
64+
@Override
65+
public void initialize(ServiceExtensionContext context) {
66+
var factory = Json.createBuilderFactory(Map.of());
67+
68+
var managementApiTransformerRegistry = transformerRegistry.forContext("management-api");
69+
70+
managementApiTransformerRegistry.register(new JsonObjectFromParticipantContextConfigurationTransformer(factory));
71+
managementApiTransformerRegistry.register(new JsonObjectToParticipantContextConfigurationTransformer());
72+
73+
webService.registerResource(ApiContext.MANAGEMENT, new ParticipantContextConfigApiV4Controller(configService, managementApiTransformerRegistry));
74+
webService.registerDynamicResource(ApiContext.MANAGEMENT, ParticipantContextConfigApiV4Controller.class, new JerseyJsonLdInterceptor(jsonLd, typeManager, JSON_LD, MANAGEMENT_SCOPE_V4, validatorRegistry, ManagementApiJsonSchema.V4.version()));
75+
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2025 Metaform Systems, Inc.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Metaform Systems, Inc. - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.virtualized.connector.controlplane.api.management.participantcontext.config.v4;
16+
17+
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
18+
import io.swagger.v3.oas.annotations.Operation;
19+
import io.swagger.v3.oas.annotations.info.Info;
20+
import io.swagger.v3.oas.annotations.media.ArraySchema;
21+
import io.swagger.v3.oas.annotations.media.Content;
22+
import io.swagger.v3.oas.annotations.media.Schema;
23+
import io.swagger.v3.oas.annotations.parameters.RequestBody;
24+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
25+
import io.swagger.v3.oas.annotations.tags.Tag;
26+
import jakarta.json.JsonObject;
27+
import jakarta.ws.rs.core.SecurityContext;
28+
import org.eclipse.edc.api.management.schema.ManagementApiJsonSchema;
29+
30+
@OpenAPIDefinition(info = @Info(title = "ParticipantContext config Management API", version = "v4alpha"))
31+
@Tag(name = "Participant Context config v4alpha")
32+
public interface ParticipantContextConfigApiV4 {
33+
34+
@Operation(description = "Set ParticipantContext config.",
35+
requestBody = @RequestBody(content = @Content(schema = @Schema(ref = ManagementApiJsonSchema.V4.PARTICIPANT_CONTEXT_CONFIG), mediaType = "application/json")),
36+
responses = {
37+
@ApiResponse(responseCode = "204", description = "The Config was set successfully"),
38+
@ApiResponse(responseCode = "400", description = "Request body was malformed, or the request could not be processed",
39+
content = @Content(array = @ArraySchema(schema = @Schema(ref = ManagementApiJsonSchema.V4.API_ERROR)), mediaType = "application/json")),
40+
@ApiResponse(responseCode = "401", description = "The request could not be completed, because either the authentication was missing or was not valid.",
41+
content = @Content(array = @ArraySchema(schema = @Schema(ref = ManagementApiJsonSchema.V4.API_ERROR)), mediaType = "application/json")),
42+
@ApiResponse(responseCode = "409", description = "Can't create the ParticipantContext, because a object with the same ID already exists",
43+
content = @Content(array = @ArraySchema(schema = @Schema(ref = ManagementApiJsonSchema.V4.API_ERROR)), mediaType = "application/json"))
44+
}
45+
)
46+
void setConfigV4(String participantContextId, JsonObject participantContext);
47+
48+
@Operation(description = "Gets ParticipantContexts config by ID.",
49+
responses = {
50+
@ApiResponse(responseCode = "200", description = "The config of the ParticipantContext",
51+
content = @Content(schema = @Schema(ref = ManagementApiJsonSchema.V4.PARTICIPANT_CONTEXT_CONFIG))),
52+
@ApiResponse(responseCode = "400", description = "Request body was malformed, or the request could not be processed",
53+
content = @Content(array = @ArraySchema(schema = @Schema(ref = ManagementApiJsonSchema.V4.API_ERROR)), mediaType = "application/json")),
54+
@ApiResponse(responseCode = "401", description = "The request could not be completed, because either the authentication was missing or was not valid.",
55+
content = @Content(array = @ArraySchema(schema = @Schema(ref = ManagementApiJsonSchema.V4.API_ERROR)), mediaType = "application/json")),
56+
@ApiResponse(responseCode = "404", description = "A ParticipantContext with the given ID does not exist.",
57+
content = @Content(array = @ArraySchema(schema = @Schema(ref = ManagementApiJsonSchema.V4.API_ERROR)), mediaType = "application/json"))
58+
}
59+
)
60+
JsonObject getConfigV4(String participantContextId, SecurityContext securityContext);
61+
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2025 Metaform Systems, Inc.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Metaform Systems, Inc. - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.virtualized.connector.controlplane.api.management.participantcontext.config.v4;
16+
17+
18+
import jakarta.annotation.security.RolesAllowed;
19+
import jakarta.json.JsonObject;
20+
import jakarta.ws.rs.Consumes;
21+
import jakarta.ws.rs.GET;
22+
import jakarta.ws.rs.PUT;
23+
import jakarta.ws.rs.Path;
24+
import jakarta.ws.rs.PathParam;
25+
import jakarta.ws.rs.Produces;
26+
import jakarta.ws.rs.core.Context;
27+
import jakarta.ws.rs.core.SecurityContext;
28+
import org.eclipse.edc.api.auth.spi.ParticipantPrincipal;
29+
import org.eclipse.edc.api.auth.spi.RequiredScope;
30+
import org.eclipse.edc.connector.controlplane.policy.spi.PolicyDefinition;
31+
import org.eclipse.edc.participantcontext.spi.config.model.ParticipantContextConfiguration;
32+
import org.eclipse.edc.participantcontext.spi.config.service.ParticipantContextConfigService;
33+
import org.eclipse.edc.participantcontext.spi.types.ParticipantContext;
34+
import org.eclipse.edc.spi.EdcException;
35+
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
36+
import org.eclipse.edc.web.spi.exception.InvalidRequestException;
37+
import org.eclipse.edc.web.spi.validation.SchemaType;
38+
39+
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
40+
import static org.eclipse.edc.participantcontext.spi.config.model.ParticipantContextConfiguration.PARTICIPANT_CONTEXT_CONFIG_TYPE_TERM;
41+
import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper;
42+
43+
@Consumes(APPLICATION_JSON)
44+
@Produces(APPLICATION_JSON)
45+
@Path("/v4alpha/participants/{participantContextId}/config")
46+
public class ParticipantContextConfigApiV4Controller implements ParticipantContextConfigApiV4 {
47+
48+
private final ParticipantContextConfigService configService;
49+
private final TypeTransformerRegistry transformerRegistry;
50+
51+
public ParticipantContextConfigApiV4Controller(ParticipantContextConfigService configService,
52+
TypeTransformerRegistry transformerRegistry) {
53+
this.configService = configService;
54+
this.transformerRegistry = transformerRegistry;
55+
}
56+
57+
@PUT
58+
@RolesAllowed({ParticipantPrincipal.ROLE_PROVISIONER})
59+
@RequiredScope("management-api:write")
60+
@Override
61+
public void setConfigV4(@PathParam("participantContextId") String participantContextId, @SchemaType(PARTICIPANT_CONTEXT_CONFIG_TYPE_TERM) JsonObject request) {
62+
63+
var config = transformerRegistry.transform(request, ParticipantContextConfiguration.class)
64+
.orElseThrow(InvalidRequestException::new)
65+
.toBuilder()
66+
.participantContextId(participantContextId)
67+
.build();
68+
69+
configService.save(config)
70+
.orElseThrow(exceptionMapper(PolicyDefinition.class, config.getParticipantContextId()));
71+
72+
}
73+
74+
@GET
75+
@RolesAllowed({ParticipantPrincipal.ROLE_PROVISIONER, ParticipantPrincipal.ROLE_ADMIN})
76+
@RequiredScope("management-api:read")
77+
@Override
78+
public JsonObject getConfigV4(@PathParam("participantContextId") String participantContextId, @Context SecurityContext securityContext) {
79+
80+
var config = configService.get(participantContextId)
81+
.orElseThrow(exceptionMapper(ParticipantContext.class, participantContextId));
82+
83+
return transformerRegistry.transform(config, JsonObject.class)
84+
.orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail()));
85+
}
86+
}

0 commit comments

Comments
 (0)