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
8 changes: 4 additions & 4 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:
- 'core/common/lib/json-ld-lib/src/main/resources/document/**'
- 'core/common/lib/jsonld-lib/src/main/resources/document/**'
- 'extensions/common/api/management-api-schema-validator/src/main/resources/schema/management/**'

jobs:
Expand All @@ -40,9 +40,9 @@ jobs:
- name: copy contexts into public folder
run: |
mkdir -p public/context
cp core/common/lib/json-ld-lib/src/main/resources/document/management-context-v1.jsonld public/context/
cp core/common/lib/json-ld-lib/src/main/resources/document/management-context-v2.jsonld public/context/
cp core/common/lib/json-ld-lib/src/main/resources/document/dspace-edc-context-v1.jsonld public/context/
cp core/common/lib/jsonld-lib/src/main/resources/document/management-context-v1.jsonld public/context/
cp core/common/lib/jsonld-lib/src/main/resources/document/management-context-v2.jsonld public/context/
cp core/common/lib/jsonld-lib/src/main/resources/document/dspace-edc-context-v1.jsonld public/context/
mkdir -p public/schema
cp -r extensions/common/api/management-api-schema-validator/src/main/resources/schema/management public/schema/
- name: deploy to gh-pages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ interface V4 {
String ASSOCIATE_DATASPACE_PROFILE_CONTEXT = EDC_MGMT_V4_SCHEMA_PREFIX + "/associate-dataspace-profile-schema.json";
String DISCOVERY_REQUEST = EDC_MGMT_V4_SCHEMA_PREFIX + "/discovery-request-schema.json";
String DISCOVERY_RESPONSE = EDC_MGMT_V4_SCHEMA_PREFIX + "/discovery-response-schema.json";
String DCP_SCOPE = EDC_MGMT_V4_SCHEMA_PREFIX + "/dcp-scope-schema.json";


static String version() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,15 @@
}
}
},
"DcpScope": {
"@id": "edc:DcpScope",
"@context": {
"type": "edc:type",
"value": "edc:value",
"profile": "edc:profile",
"prefixMapping": "edc:prefixMapping"
}
},
"inForceDate": "edc:inForceDate",
"ruleFunctions": {
"@id": "edc:ruleFunctions",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ plugins {
dependencies {
api(project(":dist:bom:controlplane-feature-dcp-bom"))
api(project(":extensions:common:iam:decentralized-claims:decentralized-claims-cel"))
api(project(":extensions:control-plane:api:management-api-v5:dcp-scope-api-v5"))
}

edcBuild {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
{
"version": "5.0.0-beta",
"urlPath": "/v5beta",
"lastUpdated": "2026-06-11T16:00:00Z",
"lastUpdated": "2026-06-25T16:00:00Z",
"maturity": "beta"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public class ManagementApiSchemaValidatorExtension implements ServiceExtension {
put(CEL_EXPRESSION_TEST_REQUEST_TYPE_TERM, V4.CEL_EXPRESSION_TEST_REQUEST);
put("AssociateDataspaceProfile", V4.ASSOCIATE_DATASPACE_PROFILE_CONTEXT);
put("DiscoveryRequest", V4.DISCOVERY_REQUEST);
put("DcpScope", V4.DCP_SCOPE);
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "DcpScopeSchema",
"type": "object",
"allOf": [
{
"$ref": "#/definitions/DcpScope"
}
],
"$id": "https://w3id.org/edc/connector/management/schema/v4/dcp-scope-schema.json",
"definitions": {
"DcpScope": {
"type": "object",
"properties": {
"@context": {
"$ref": "https://w3id.org/edc/connector/management/schema/v4/context-schema.json"
},
"@type": {
"type": "string",
"const": "DcpScope"
},
"@id": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"DEFAULT",
"POLICY"
]
},
"value": {
"type": "string"
},
"profile": {
"type": "string"
},
"prefixMapping": {
"type": "string"
}
},
"required": [
"@context",
"@type",
"value"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@
import org.eclipse.edc.spi.query.Criterion;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.result.ServiceResult;
import org.eclipse.edc.spi.result.StoreResult;
import org.eclipse.edc.transaction.spi.TransactionContext;

import java.util.List;

import static org.eclipse.edc.spi.query.Criterion.criterion;

/**
* Implementation of {@link DcpScopeRegistry}.
*/
Expand All @@ -42,11 +45,41 @@ public ServiceResult<Void> register(DcpScope scope) {
return transactionContext.execute(() -> store.save(scope).flatMap(ServiceResult::from));
}

@Override
public ServiceResult<Void> create(DcpScope scope) {
return transactionContext.execute(() -> findById(scope.getId())
.compose(existing -> existing.isEmpty()
? store.save(scope)
: StoreResult.<Void>alreadyExists("DcpScope with id %s already exists".formatted(scope.getId())))
.flatMap(ServiceResult::from));
}

@Override
public ServiceResult<Void> update(DcpScope scope) {
return transactionContext.execute(() -> findById(scope.getId())
.compose(existing -> existing.isEmpty()
? StoreResult.<Void>notFound("DcpScope with id %s does not exist".formatted(scope.getId()))
: store.save(scope))
.flatMap(ServiceResult::from));
}

@Override
public ServiceResult<List<DcpScope>> query(QuerySpec spec) {
return transactionContext.execute(() -> store.query(spec).flatMap(ServiceResult::from));
}

@Override
public ServiceResult<Void> remove(String scopeId) {
return transactionContext.execute(() -> store.delete(scopeId).flatMap(ServiceResult::from));
}

private StoreResult<List<DcpScope>> findById(String id) {
var query = QuerySpec.Builder.newInstance()
.filter(criterion("id", "=", id))
.build();
return store.query(query);
}

@Override
public ServiceResult<List<DcpScope>> getDefaultScopes() {
var query = QuerySpec.Builder.newInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ public StoreResult<Void> save(DcpScope scope) {

@Override
public StoreResult<Void> delete(String scopeId) {
scopes.remove(scopeId);
return StoreResult.success();
return scopes.remove(scopeId) != null
? StoreResult.success()
: StoreResult.notFound(notFoundErrorMessage(scopeId));
}


@Override
public StoreResult<List<DcpScope>> query(QuerySpec spec) {
return StoreResult.success(queryResolver.query(scopes.values().stream(), spec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.edc.iam.decentralizedclaims.spi.scope.DcpScope;
import org.eclipse.edc.iam.decentralizedclaims.spi.scope.store.DcpScopeStore;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.result.StoreResult;
import org.eclipse.edc.transaction.spi.NoopTransactionContext;
import org.eclipse.edc.transaction.spi.TransactionContext;
Expand All @@ -26,6 +27,7 @@
import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -71,6 +73,69 @@ void register_should_return_failure_when_store_fails() {
verify(store).save(scope);
}

@Test
void create_should_save_when_scope_does_not_exist() {
var scope = DcpScope.Builder.newInstance().id("s1").value("v").profile("p").build();
when(store.query(any())).thenReturn(StoreResult.success(List.of()));
when(store.save(scope)).thenReturn(StoreResult.success());

var impl = new DcpScopeRegistryImpl(transactionContext, store);
var res = impl.create(scope);

assertThat(res).isSucceeded();
verify(store).save(scope);
}

@Test
void create_should_return_conflict_when_scope_already_exists() {
var scope = DcpScope.Builder.newInstance().id("s1").value("v").profile("p").build();
when(store.query(any())).thenReturn(StoreResult.success(List.of(scope)));

var impl = new DcpScopeRegistryImpl(transactionContext, store);
var res = impl.create(scope);

assertThat(res).isFailed().detail().contains("already exists");
verify(store, never()).save(any());
}

@Test
void update_should_save_when_scope_exists() {
var scope = DcpScope.Builder.newInstance().id("s1").value("v").profile("p").build();
when(store.query(any())).thenReturn(StoreResult.success(List.of(scope)));
when(store.save(scope)).thenReturn(StoreResult.success());

var impl = new DcpScopeRegistryImpl(transactionContext, store);
var res = impl.update(scope);

assertThat(res).isSucceeded();
verify(store).save(scope);
}

@Test
void update_should_return_not_found_when_scope_does_not_exist() {
var scope = DcpScope.Builder.newInstance().id("s1").value("v").profile("p").build();
when(store.query(any())).thenReturn(StoreResult.success(List.of()));

var impl = new DcpScopeRegistryImpl(transactionContext, store);
var res = impl.update(scope);

assertThat(res).isFailed().detail().contains("does not exist");
verify(store, never()).save(any());
}

@Test
void query_should_return_list_from_store() {
var s1 = DcpScope.Builder.newInstance().id("s1").value("v1").profile("p").build();
var expected = List.of(s1);
when(store.query(any())).thenReturn(StoreResult.success(expected));

var impl = new DcpScopeRegistryImpl(transactionContext, store);
var res = impl.query(QuerySpec.max());

assertThat(res).isSucceeded().isEqualTo(expected);
verify(store).query(QuerySpec.max());
}

@Test
void remove_should_delegate_to_store_and_return_success() {
when(store.delete("id")).thenReturn(StoreResult.success());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ public StoreResult<Void> save(DcpScope scope) {
public StoreResult<Void> delete(String scopeId) {
return transactionContext.execute(() -> {
try (var connection = getConnection()) {
queryExecutor.execute(connection, statements.getDeleteTemplate(), scopeId);
var deleted = queryExecutor.execute(connection, statements.getDeleteTemplate(), scopeId);
if (deleted == 0) {
return StoreResult.notFound("DcpScope with id %s not found".formatted(scopeId));
}
return StoreResult.success();
} catch (SQLException e) {
throw new EdcPersistenceException(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2026 Metaform Systems, Inc.
*
* 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:
* Metaform Systems, Inc. - initial API and implementation
*
*/

plugins {
`java-library`
id(libs.plugins.swagger.get().pluginId)
}

dependencies {
api(project(":spi:core-spi"))
api(project(":spi:control-plane-spi"))
api(project(":spi:decentralized-claims-spi"))

implementation(project(":core:common:lib:core-lib"))
implementation(libs.jakarta.rsApi)
implementation(libs.jakarta.annotation)

testImplementation(testFixtures(project(":extensions:common:http:jersey-core")))
testImplementation(testFixtures(project(":core:common:lib:jsonld-lib")))
testImplementation(libs.restAssured)
testImplementation(libs.awaitility)
}

edcBuild {
swagger {
apiGroup("management-api")
}
}
Loading
Loading