-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implements credential definition vertical
- Loading branch information
Showing
41 changed files
with
2,229 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
...java/org/eclipse/edc/issuerservice/defaults/store/InMemoryAttestationDefinitionStore.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (c) 2025 Cofinity-X | ||
* | ||
* 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: | ||
* Cofinity-X - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.issuerservice.defaults.store; | ||
|
||
import org.eclipse.edc.identityhub.spi.issuance.credentials.attestation.AttestationDefinitionStore; | ||
import org.eclipse.edc.identityhub.spi.issuance.credentials.model.AttestationDefinition; | ||
import org.eclipse.edc.identityhub.store.InMemoryEntityStore; | ||
import org.eclipse.edc.spi.query.QueryResolver; | ||
import org.eclipse.edc.spi.result.StoreResult; | ||
import org.eclipse.edc.store.ReflectionBasedQueryResolver; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class InMemoryAttestationDefinitionStore extends InMemoryEntityStore<AttestationDefinition> implements AttestationDefinitionStore { | ||
|
||
@Override | ||
public @Nullable AttestationDefinition resolveDefinition(String id) { | ||
return store.get(id); | ||
} | ||
|
||
@Override | ||
public StoreResult<Void> delete(String id) { | ||
return super.deleteById(id); | ||
} | ||
|
||
@Override | ||
protected String getId(AttestationDefinition newObject) { | ||
return newObject.id(); | ||
} | ||
|
||
@Override | ||
protected QueryResolver<AttestationDefinition> createQueryResolver() { | ||
return new ReflectionBasedQueryResolver<>(AttestationDefinition.class, criterionOperatorRegistry); | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
.../java/org/eclipse/edc/issuerservice/defaults/store/InMemoryCredentialDefinitionStore.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* Copyright (c) 2025 Cofinity-X | ||
* | ||
* 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: | ||
* Cofinity-X - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.issuerservice.defaults.store; | ||
|
||
import org.eclipse.edc.identityhub.spi.issuance.credentials.model.CredentialDefinition; | ||
import org.eclipse.edc.identityhub.store.InMemoryEntityStore; | ||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.store.CredentialDefinitionStore; | ||
import org.eclipse.edc.spi.query.QueryResolver; | ||
import org.eclipse.edc.spi.result.StoreResult; | ||
import org.eclipse.edc.store.ReflectionBasedQueryResolver; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
import static org.eclipse.edc.spi.result.StoreResult.alreadyExists; | ||
import static org.eclipse.edc.spi.result.StoreResult.notFound; | ||
import static org.eclipse.edc.spi.result.StoreResult.success; | ||
|
||
public class InMemoryCredentialDefinitionStore extends InMemoryEntityStore<CredentialDefinition> implements CredentialDefinitionStore { | ||
|
||
|
||
private final Map<String, String> credentialTypes = new HashMap<>(); | ||
|
||
@Override | ||
public StoreResult<Void> create(CredentialDefinition credentialDefinition) { | ||
lock.writeLock().lock(); | ||
try { | ||
if (credentialTypes.containsKey(credentialDefinition.getCredentialType())) { | ||
return alreadyExists(alreadyExistsForTypeErrorMessage(credentialDefinition.getCredentialType())); | ||
} | ||
if (store.containsKey(credentialDefinition.getId())) { | ||
return alreadyExists(alreadyExistsErrorMessage(credentialDefinition.getId())); | ||
} | ||
store.put(credentialDefinition.getId(), credentialDefinition); | ||
credentialTypes.put(credentialDefinition.getCredentialType(), credentialDefinition.getId()); | ||
return success(null); | ||
} finally { | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
public StoreResult<Void> update(CredentialDefinition credentialDefinition) { | ||
lock.writeLock().lock(); | ||
try { | ||
if (!store.containsKey(credentialDefinition.getId())) { | ||
return notFound(notFoundErrorMessage(credentialDefinition.getId())); | ||
} | ||
var credentialId = credentialTypes.get(credentialDefinition.getCredentialType()); | ||
if (credentialId != null && !credentialId.equals(credentialDefinition.getId())) { | ||
return alreadyExists(alreadyExistsForTypeErrorMessage(credentialDefinition.getCredentialType())); | ||
} | ||
var oldDefinition = store.put(credentialDefinition.getId(), credentialDefinition); | ||
|
||
Optional.ofNullable(oldDefinition) | ||
.map(CredentialDefinition::getCredentialType) | ||
.ifPresent(credentialTypes::remove); | ||
|
||
return success(); | ||
} finally { | ||
Check notice Code scanning / CodeQL Missing Override annotation Note
This method overrides
InMemoryEntityStore.deleteById Error loading related location Loading This method overrides CredentialDefinitionStore.deleteById Error loading related location Loading |
||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
public StoreResult<Void> deleteById(String id) { | ||
lock.writeLock().lock(); | ||
try { | ||
if (!store.containsKey(id)) { | ||
return notFound(notFoundErrorMessage(id)); | ||
} | ||
var credential = store.remove(id); | ||
credentialTypes.remove(credential.getCredentialType()); | ||
return success(); | ||
} finally { | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
protected String getId(CredentialDefinition newObject) { | ||
return newObject.getId(); | ||
} | ||
|
||
@Override | ||
protected QueryResolver<CredentialDefinition> createQueryResolver() { | ||
return new ReflectionBasedQueryResolver<>(CredentialDefinition.class, criterionOperatorRegistry); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
...a/org/eclipse/edc/issuerservice/defaults/store/InMemoryCredentialDefinitionStoreTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright (c) 2025 Cofinity-X | ||
* | ||
* 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: | ||
* Cofinity-X - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.issuerservice.defaults.store; | ||
|
||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.store.CredentialDefinitionStore; | ||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.store.CredentialDefinitionStoreTestBase; | ||
|
||
public class InMemoryCredentialDefinitionStoreTest extends CredentialDefinitionStoreTestBase { | ||
|
||
private final InMemoryCredentialDefinitionStore store = new InMemoryCredentialDefinitionStore(); | ||
|
||
@Override | ||
protected CredentialDefinitionStore getStore() { | ||
return store; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
core/issuerservice/issuerservice-credential-definitions/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
plugins { | ||
`java-library` | ||
} | ||
|
||
dependencies { | ||
api(project(":spi:issuerservice:issuerservice-credential-definition-spi")) | ||
api(project(":spi:issuance-credentials-spi")) | ||
|
||
implementation(libs.edc.spi.transaction) | ||
implementation(libs.edc.lib.store) | ||
testImplementation(libs.edc.junit) | ||
testImplementation(testFixtures(project(":spi:issuerservice:issuerservice-credential-definition-spi"))) | ||
|
||
} |
43 changes: 43 additions & 0 deletions
43
.../eclipse/edc/issuerservice/credentialdefinition/CredentialDefinitionServiceExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright (c) 2025 Cofinity-X | ||
* | ||
* 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: | ||
* Cofinity-X - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.issuerservice.credentialdefinition; | ||
|
||
import org.eclipse.edc.identityhub.spi.issuance.credentials.attestation.AttestationDefinitionStore; | ||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.CredentialDefinitionService; | ||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.store.CredentialDefinitionStore; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Extension; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Inject; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Provider; | ||
import org.eclipse.edc.spi.system.ServiceExtension; | ||
import org.eclipse.edc.transaction.spi.TransactionContext; | ||
|
||
import static org.eclipse.edc.issuerservice.credentialdefinition.CredentialDefinitionServiceExtension.NAME; | ||
|
||
@Extension(value = NAME) | ||
public class CredentialDefinitionServiceExtension implements ServiceExtension { | ||
public static final String NAME = "IssuerService Credential Definition Service Extension"; | ||
@Inject | ||
private TransactionContext transactionContext; | ||
@Inject | ||
private CredentialDefinitionStore store; | ||
|
||
@Inject | ||
private AttestationDefinitionStore attestationDefinitionStore; | ||
|
||
@Provider | ||
public CredentialDefinitionService getParticipantService() { | ||
return new CredentialDefinitionServiceImpl(transactionContext, store, attestationDefinitionStore); | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
...a/org/eclipse/edc/issuerservice/credentialdefinition/CredentialDefinitionServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright (c) 2025 Cofinity-X | ||
* | ||
* 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: | ||
* Cofinity-X - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.issuerservice.credentialdefinition; | ||
|
||
import org.eclipse.edc.identityhub.spi.issuance.credentials.attestation.AttestationDefinitionStore; | ||
import org.eclipse.edc.identityhub.spi.issuance.credentials.model.AttestationDefinition; | ||
import org.eclipse.edc.identityhub.spi.issuance.credentials.model.CredentialDefinition; | ||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.CredentialDefinitionService; | ||
import org.eclipse.edc.issuerservice.spi.credentialdefinition.store.CredentialDefinitionStore; | ||
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.transaction.spi.TransactionContext; | ||
|
||
import java.util.Collection; | ||
import java.util.stream.Collectors; | ||
|
||
import static org.eclipse.edc.spi.result.ServiceResult.from; | ||
|
||
public class CredentialDefinitionServiceImpl implements CredentialDefinitionService { | ||
private final TransactionContext transactionContext; | ||
private final CredentialDefinitionStore credentialDefinitionStore; | ||
private final AttestationDefinitionStore attestationDefinitionStore; | ||
|
||
public CredentialDefinitionServiceImpl(TransactionContext transactionContext, CredentialDefinitionStore credentialDefinitionStore, AttestationDefinitionStore attestationDefinitionStore) { | ||
this.transactionContext = transactionContext; | ||
this.credentialDefinitionStore = credentialDefinitionStore; | ||
this.attestationDefinitionStore = attestationDefinitionStore; | ||
} | ||
|
||
@Override | ||
public ServiceResult<Void> createCredentialDefinition(CredentialDefinition credentialDefinition) { | ||
return transactionContext.execute(() -> internalCreate(credentialDefinition)); | ||
|
||
} | ||
|
||
@Override | ||
public ServiceResult<Void> deleteCredentialDefinition(String credentialDefinitionId) { | ||
return transactionContext.execute(() -> from(credentialDefinitionStore.deleteById(credentialDefinitionId))); | ||
} | ||
|
||
@Override | ||
public ServiceResult<Void> updateCredentialDefinition(CredentialDefinition credentialDefinition) { | ||
return transactionContext.execute(() -> internalUpdate(credentialDefinition)); | ||
} | ||
|
||
@Override | ||
public ServiceResult<Collection<CredentialDefinition>> queryCredentialDefinitions(QuerySpec querySpec) { | ||
return transactionContext.execute(() -> from(credentialDefinitionStore.query(querySpec))); | ||
|
||
} | ||
|
||
@Override | ||
public ServiceResult<CredentialDefinition> findById(String credentialDefinitionId) { | ||
return transactionContext.execute(() -> from(credentialDefinitionStore.findById(credentialDefinitionId))); | ||
|
||
} | ||
|
||
private ServiceResult<Void> internalCreate(CredentialDefinition credentialDefinition) { | ||
return validateAttestations(credentialDefinition) | ||
.compose(u -> from(credentialDefinitionStore.create(credentialDefinition))); | ||
} | ||
|
||
private ServiceResult<Void> internalUpdate(CredentialDefinition credentialDefinition) { | ||
return validateAttestations(credentialDefinition) | ||
.compose(u -> from(credentialDefinitionStore.update(credentialDefinition))); | ||
} | ||
|
||
private ServiceResult<Void> validateAttestations(CredentialDefinition credentialDefinition) { | ||
var query = QuerySpec.Builder.newInstance() | ||
.filter(Criterion.criterion("id", "in", credentialDefinition.getAttestations())) | ||
.build(); | ||
return from(attestationDefinitionStore.query(query)) | ||
.compose(attestationDefinitions -> checkAttestations(credentialDefinition, attestationDefinitions)); | ||
} | ||
|
||
private ServiceResult<Void> checkAttestations(CredentialDefinition credentialDefinition, Collection<AttestationDefinition> attestationDefinitions) { | ||
if (attestationDefinitions.size() != credentialDefinition.getAttestations().size()) { | ||
|
||
var attestationsIds = attestationDefinitions.stream().map(AttestationDefinition::id).collect(Collectors.toSet()); | ||
|
||
var missingAttestations = credentialDefinition.getAttestations().stream() | ||
.filter(attestationId -> !attestationsIds.contains(attestationId)) | ||
.collect(Collectors.toSet()); | ||
|
||
return ServiceResult.badRequest("Attestation definitions [%s] not found".formatted(String.join(",", missingAttestations))); | ||
} | ||
return ServiceResult.success(); | ||
} | ||
} |
Oops, something went wrong.