Skip to content

Commit

Permalink
feat: check if DID exists before creating a participant (#429)
Browse files Browse the repository at this point in the history
* feat: check if DID exists before creating a participant

* trigger ci

* use randomized participant did on every run
  • Loading branch information
paullatzelsperger authored Aug 26, 2024
1 parent df5e38b commit f11d504
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.eclipse.edc.identityhub.participantcontext;

import org.eclipse.edc.identithub.spi.did.DidDocumentService;
import org.eclipse.edc.identithub.spi.did.store.DidResourceStore;
import org.eclipse.edc.identityhub.spi.keypair.KeyPairService;
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextCreated;
Expand Down Expand Up @@ -54,6 +55,8 @@ public class ParticipantContextExtension implements ServiceExtension {
private Clock clock;
@Inject
private EventRouter eventRouter;
@Inject
private DidResourceStore didResourceStore;

private ParticipantContextObservable participantContextObservable;

Expand All @@ -72,7 +75,7 @@ public void initialize(ServiceExtensionContext context) {

@Provider
public ParticipantContextService createParticipantService() {
return new ParticipantContextServiceImpl(participantContextStore, vault, transactionContext, participantContextObservable());
return new ParticipantContextServiceImpl(participantContextStore, didResourceStore, vault, transactionContext, participantContextObservable());
}

@Provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.eclipse.edc.identityhub.participantcontext;

import org.eclipse.edc.identithub.spi.did.store.DidResourceStore;
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextObservable;
import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantContext;
Expand Down Expand Up @@ -45,13 +46,15 @@ public class ParticipantContextServiceImpl implements ParticipantContextService

private static final String API_KEY_ALIAS_SUFFIX = "apikey";
private final ParticipantContextStore participantContextStore;
private final DidResourceStore didResourceStore;
private final Vault vault;
private final TransactionContext transactionContext;
private final ApiTokenGenerator tokenGenerator;
private final ParticipantContextObservable observable;

public ParticipantContextServiceImpl(ParticipantContextStore participantContextStore, Vault vault, TransactionContext transactionContext, ParticipantContextObservable observable) {
public ParticipantContextServiceImpl(ParticipantContextStore participantContextStore, DidResourceStore didResourceStore, Vault vault, TransactionContext transactionContext, ParticipantContextObservable observable) {
this.participantContextStore = participantContextStore;
this.didResourceStore = didResourceStore;
this.vault = vault;
this.transactionContext = transactionContext;
this.observable = observable;
Expand All @@ -61,6 +64,9 @@ public ParticipantContextServiceImpl(ParticipantContextStore participantContextS
@Override
public ServiceResult<String> createParticipantContext(ParticipantManifest manifest) {
return transactionContext.execute(() -> {
if (didResourceStore.findById(manifest.getDid()) != null) {
return ServiceResult.conflict("Another participant with the same DID '%s' already exists.".formatted(manifest.getDid()));
}
var apiKey = new AtomicReference<String>();
var context = convert(manifest);
var res = createParticipantContext(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.gen.OctetKeyPairGenerator;
import org.assertj.core.api.Assertions;
import org.eclipse.edc.identithub.spi.did.model.DidResource;
import org.eclipse.edc.identithub.spi.did.store.DidResourceStore;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextObservable;
import org.eclipse.edc.identityhub.spi.participantcontext.model.KeyDescriptor;
import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantContext;
Expand Down Expand Up @@ -56,13 +58,14 @@ class ParticipantContextServiceImplTest {
private final Vault vault = mock();
private final ParticipantContextStore participantContextStore = mock();
private final ParticipantContextObservable observableMock = mock();
private final DidResourceStore didResourceStore = mock();
private ParticipantContextServiceImpl participantContextService;

@BeforeEach
void setUp() {
var keyParserRegistry = new KeyParserRegistryImpl();
keyParserRegistry.register(new PemParser(mock()));
participantContextService = new ParticipantContextServiceImpl(participantContextStore, vault, new NoopTransactionContext(), observableMock);
participantContextService = new ParticipantContextServiceImpl(participantContextStore, didResourceStore, vault, new NoopTransactionContext(), observableMock);
}

@ParameterizedTest(name = "isActive: {0}")
Expand Down Expand Up @@ -159,6 +162,18 @@ void createParticipantContext_whenExists() {

}

@Test
void createParticipantContext_whenDidExists() {
var ctx = createManifest().build();
when(didResourceStore.findById(anyString())).thenReturn(DidResource.Builder.newInstance().did(ctx.getDid()).build());

assertThat(participantContextService.createParticipantContext(ctx)).isFailed()
.detail().isEqualTo("Another participant with the same DID '%s' already exists.".formatted(ctx.getDid()));

verify(didResourceStore).findById(eq(ctx.getDid()));
verifyNoMoreInteractions(didResourceStore, participantContextStore, observableMock);
}

@Test
void getParticipantContext() {
var ctx = createContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

import io.restassured.http.ContentType;
import io.restassured.http.Header;
import org.eclipse.edc.iam.did.spi.document.DidDocument;
import org.eclipse.edc.identithub.spi.did.model.DidResource;
import org.eclipse.edc.identithub.spi.did.store.DidResourceStore;
import org.eclipse.edc.identityhub.spi.keypair.model.KeyPairState;
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextCreated;
Expand Down Expand Up @@ -52,6 +55,7 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;

Expand Down Expand Up @@ -108,7 +112,7 @@ void getUserById_notOwner_expect403(IdentityHubEndToEndTestContext context) {
}

@Test
void createNewUser_principalIsSuperser(IdentityHubEndToEndTestContext context, EventRouter router) {
void createNewUser_principalIsSuperuser(IdentityHubEndToEndTestContext context, EventRouter router) {
var subscriber = mock(EventSubscriber.class);
router.registerSync(ParticipantContextCreated.class, subscriber);
var apikey = context.createSuperUser();
Expand Down Expand Up @@ -165,7 +169,6 @@ void createNewUser_verifyKeyPairActive(boolean isActive, IdentityHubEndToEndTest

}


@Test
void createNewUser_principalIsNotSuperuser_expect403(IdentityHubEndToEndTestContext context, EventRouter router) {
var subscriber = mock(EventSubscriber.class);
Expand Down Expand Up @@ -215,6 +218,28 @@ void createNewUser_principalIsKnown_expect401(IdentityHubEndToEndTestContext con
assertThat(context.getKeyPairsForParticipant(manifest.getParticipantId())).isEmpty();
}

@Test
void createNewUser_whenDidAlreadyExists_expect409(IdentityHubEndToEndTestContext context, DidResourceStore didResourceStore, EventRouter router) {
var subscriber = mock(EventSubscriber.class);
router.registerSync(ParticipantContextCreated.class, subscriber);
var apikey = context.createSuperUser();

var manifest = context.createNewParticipant().build();

didResourceStore.save(DidResource.Builder.newInstance().did(manifest.getDid()).document(DidDocument.Builder.newInstance().build()).build());

context.getIdentityApiEndpoint().baseRequest()
.header(new Header("x-api-key", apikey))
.contentType(ContentType.JSON)
.body(manifest)
.post("/v1alpha/participants/")
.then()
.log().ifValidationFails()
.statusCode(409);

verify(subscriber, never()).on(argThat(env -> ((ParticipantContextCreated) env.getPayload()).getParticipantId().equals(manifest.getParticipantId())));
}

@Test
void activateParticipant_principalIsSuperser(IdentityHubEndToEndTestContext context, ParticipantContextService participantContextService, EventRouter router) {
var superUserKey = context.createSuperUser();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public ParticipantManifest.Builder createNewParticipant() {
return ParticipantManifest.Builder.newInstance()
.participantId("another-participant")
.active(false)
.did("did:web:another:participant")
.did("did:web:another:participant:" + UUID.randomUUID())
.serviceEndpoint(new Service("test-service", "test-service-type", "https://test.com"))
.key(createKeyDescriptor().build());
}
Expand Down

0 comments on commit f11d504

Please sign in to comment.