Skip to content

Commit

Permalink
feat: activate ParticipantContext explicitly during creation (#457)
Browse files Browse the repository at this point in the history
* feat: activate ParticipantContext explicitly during creation

* DEPENDENCIES
  • Loading branch information
paullatzelsperger authored Sep 12, 2024
1 parent fccc410 commit db0206e
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 37 deletions.
40 changes: 20 additions & 20 deletions DEPENDENCIES
Original file line number Diff line number Diff line change
Expand Up @@ -302,26 +302,26 @@ maven/mavencentral/org.eclipse.edc/version-api/0.10.0-SNAPSHOT, Apache-2.0, appr
maven/mavencentral/org.eclipse.edc/web-spi/0.10.0-SNAPSHOT, Apache-2.0, approved, technology.edc
maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-common/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-server/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-jakarta-client/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-jakarta-common/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-jakarta-server/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-servlet/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-alpn-client/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-annotations/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-client/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-http/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-io/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-jndi/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-plus/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-security/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-server/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.23, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-common/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-server/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-jakarta-client/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-jakarta-common/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-jakarta-server/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty.websocket/websocket-servlet/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-alpn-client/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-annotations/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-client/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-http/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-io/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-jndi/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-plus/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-security/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-server/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.24, EPL-2.0 OR Apache-2.0, approved, rt.jetty
maven/mavencentral/org.eclipse.parsson/parsson/1.1.7, EPL-2.0, approved, ee4j.parsson
maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.6, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish
maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.6, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ public ServiceResult<Void> publish(String did) {
success() :
ServiceResult.badRequest(publishResult.getFailureDetail());
}
return ServiceResult.badRequest(("Cannot publish DID '%s' for participant '%s' because the ParticipantContext is not state '%s' state, " +
"but was '%s'.")
return ServiceResult.badRequest(("Cannot publish DID '%s' for participant '%s' because the ParticipantContext state is not '%s', " +
"but '%s'.")
.formatted(did, participantId, ParticipantContextState.ACTIVATED, state));
});
});
Expand Down Expand Up @@ -158,10 +158,10 @@ public ServiceResult<Void> unpublish(String did) {
success() :
ServiceResult.badRequest(publishResult.getFailureDetail());
}
monitor.info("Unpublishing DID Document '%s': not in state '%s', unpublishing is a NOOP.".formatted(did, existingResource.getStateAsEnum()));
monitor.info("Unpublishing DID Document '%s' in state '%s', unpublishing is a NOOP.".formatted(did, existingResource.getStateAsEnum()));
return success();
}
return ServiceResult.badRequest(("Cannot un-publish DID '%s' for participant '%s' because the ParticipantContext is not state '%s' state, " +
return ServiceResult.badRequest(("Cannot un-publish DID '%s' for participant '%s' because the ParticipantContext is not '%s' state, " +
"but was '%s'.")
.formatted(did, participantId, ParticipantContextState.DEACTIVATED, state));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.edc.identithub.spi.did.DidDocumentService;
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;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextDeleting;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
Expand All @@ -40,6 +41,8 @@ public class ParticipantContextCoordinatorExtension implements ServiceExtension
private Clock clock;
@Inject
private EventRouter eventRouter;
@Inject
private ParticipantContextService participantContextService;

@Override
public String name() {
Expand All @@ -49,7 +52,7 @@ public String name() {
@Override
public void initialize(ServiceExtensionContext context) {
var coordinator = new ParticipantContextEventCoordinator(context.getMonitor().withPrefix("ParticipantContextEventCoordinator"),
didDocumentService, keyPairService);
didDocumentService, keyPairService, participantContextService);

eventRouter.registerSync(ParticipantContextCreated.class, coordinator);
eventRouter.registerSync(ParticipantContextDeleting.class, coordinator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import org.eclipse.edc.identithub.spi.did.DidDocumentService;
import org.eclipse.edc.identityhub.spi.keypair.KeyPairService;
import org.eclipse.edc.identityhub.spi.keypair.model.KeyPairResource;
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextCreated;
import org.eclipse.edc.identityhub.spi.participantcontext.events.ParticipantContextDeleting;
import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantContext;
import org.eclipse.edc.spi.event.Event;
import org.eclipse.edc.spi.event.EventEnvelope;
import org.eclipse.edc.spi.event.EventSubscriber;
Expand Down Expand Up @@ -47,11 +49,13 @@ class ParticipantContextEventCoordinator implements EventSubscriber {
private final Monitor monitor;
private final DidDocumentService didDocumentService;
private final KeyPairService keyPairService;
private final ParticipantContextService participantContextService;

ParticipantContextEventCoordinator(Monitor monitor, DidDocumentService didDocumentService, KeyPairService keyPairService) {
ParticipantContextEventCoordinator(Monitor monitor, DidDocumentService didDocumentService, KeyPairService keyPairService, ParticipantContextService participantContextService) {
this.monitor = monitor;
this.didDocumentService = didDocumentService;
this.keyPairService = keyPairService;
this.participantContextService = participantContextService;
}

@Override
Expand All @@ -71,9 +75,11 @@ public <E extends Event> void on(EventEnvelope<E> event) {
}

didDocumentService.store(doc, manifest.getParticipantId())
// adding the keypair event will cause the DidDocumentService to update the DID.
// adding the keypair event will cause the DidDocumentService to update the DID
.compose(u -> keyPairService.addKeyPair(createdEvent.getParticipantId(), createdEvent.getManifest().getKey(), true))
.compose(u -> manifest.isActive() ? didDocumentService.publish(doc.getId()) : success())
.compose(u -> manifest.isActive()
? participantContextService.updateParticipant(manifest.getParticipantId(), ParticipantContext::activate) //implicitly publishes the did document
: success())
.onFailure(f -> monitor.warning("%s".formatted(f.getFailureDetail())));

} else if (payload instanceof ParticipantContextDeleting deletionEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private ParticipantContext convert(ParticipantManifest manifest) {
.roles(manifest.getRoles())
.did(manifest.getDid())
.apiTokenAlias("%s-%s".formatted(manifest.getParticipantId(), API_KEY_ALIAS_SUFFIX))
.state(manifest.isActive() ? ParticipantContextState.ACTIVATED : ParticipantContextState.CREATED)
.state(ParticipantContextState.CREATED)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.edc.identithub.spi.did.DidDocumentService;
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;
import org.eclipse.edc.identityhub.spi.participantcontext.model.KeyDescriptor;
import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantManifest;
Expand All @@ -24,6 +25,7 @@
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.ServiceResult;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.time.Instant;
Expand All @@ -44,7 +46,14 @@ class ParticipantContextEventCoordinatorTest {
private final Monitor monitor = mock();
private final DidDocumentService didDocumentService = mock();
private final KeyPairService keyPairService = mock();
private final ParticipantContextEventCoordinator coordinator = new ParticipantContextEventCoordinator(monitor, didDocumentService, keyPairService);
private final ParticipantContextService participantContextService = mock();
private final ParticipantContextEventCoordinator coordinator = new ParticipantContextEventCoordinator(monitor, didDocumentService, keyPairService, participantContextService);

@BeforeEach
void setup() {
when(participantContextService.updateParticipant(anyString(), any()))
.thenReturn(ServiceResult.success());
}

@Test
void onParticipantCreated() {
Expand All @@ -59,7 +68,6 @@ void onParticipantCreated() {
.build()));

verify(didDocumentService).store(any(), eq(participantId));
verify(didDocumentService).publish(eq("did:web:" + participantId));
verify(keyPairService).addKeyPair(eq(participantId), any(), eq(true));
verifyNoMoreInteractions(keyPairService, didDocumentService, monitor);
}
Expand All @@ -84,7 +92,6 @@ void onParticipantCreated_active_didDocumentServicePublishFailure() {
var participantId = "test-id";
when(didDocumentService.store(any(), eq(participantId))).thenReturn(ServiceResult.success());
when(keyPairService.addKeyPair(eq(participantId), any(), anyBoolean())).thenReturn(ServiceResult.success());
when(didDocumentService.publish(anyString())).thenReturn(ServiceResult.badRequest("foobar"));

coordinator.on(envelope(ParticipantContextCreated.Builder.newInstance()
.participantId(participantId)
Expand All @@ -93,8 +100,6 @@ void onParticipantCreated_active_didDocumentServicePublishFailure() {

verify(didDocumentService).store(any(), eq(participantId));
verify(keyPairService).addKeyPair(eq(participantId), any(), eq(true));
verify(didDocumentService).publish(anyString());
verify(monitor).warning("foobar");
verifyNoMoreInteractions(didDocumentService);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void publishDid_participantNotActivated_expect400(IdentityHubEndToEndTestContext
.then()
.log().ifValidationFails()
.statusCode(400)
.body(Matchers.containsString("Cannot publish DID 'did:web:test-user' for participant 'test-user' because the ParticipantContext is not state 'ACTIVATED' state, but was 'CREATED'."));
.body(Matchers.containsString("Cannot publish DID 'did:web:test-user' for participant 'test-user' because the ParticipantContext state is not 'ACTIVATED', but 'CREATED'."));

// verify that the publish event was fired twice
verifyNoInteractions(subscriber);
Expand Down Expand Up @@ -291,7 +291,7 @@ void unpublishDid_participantActive_expect400(IdentityHubEndToEndTestContext con
.then()
.log().ifValidationFails()
.statusCode(400)
.body(Matchers.containsString("Cannot un-publish DID 'did:web:test-user' for participant 'test-user' because the ParticipantContext is not state 'DEACTIVATED' state, but was 'ACTIVATED'."));
.body(Matchers.containsString("Cannot un-publish DID 'did:web:test-user' for participant 'test-user' because the ParticipantContext is not 'DEACTIVATED' state, but was 'ACTIVATED'."));

// verify that the unpublish event was fired
verifyNoInteractions(subscriber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.edc.identithub.spi.did.DidConstants;
import org.eclipse.edc.identithub.spi.did.DidDocumentPublisher;
import org.eclipse.edc.identithub.spi.did.DidDocumentPublisherRegistry;
import org.eclipse.edc.identithub.spi.did.events.DidDocumentPublished;
import org.eclipse.edc.identithub.spi.did.model.DidResource;
import org.eclipse.edc.identithub.spi.did.model.DidState;
import org.eclipse.edc.identithub.spi.did.store.DidResourceStore;
Expand Down Expand Up @@ -65,6 +66,7 @@
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -166,6 +168,8 @@ void createNewUser_whenKeyPairActive(IdentityHubEndToEndTestContext context, Eve
.key(context.createKeyDescriptor().active(true).build())
.build();

router.registerSync(DidDocumentPublished.class, subscriber);

context.getIdentityApiEndpoint().baseRequest()
.header(new Header("x-api-key", apikey))
.contentType(ContentType.JSON)
Expand All @@ -176,7 +180,8 @@ void createNewUser_whenKeyPairActive(IdentityHubEndToEndTestContext context, Eve
.statusCode(anyOf(equalTo(200), equalTo(204)))
.body(notNullValue());

verify(subscriber).on(argThat(env -> ((ParticipantContextCreated) env.getPayload()).getParticipantId().equals(manifest.getParticipantId())));
verify(subscriber).on(argThat(env -> env.getPayload() instanceof ParticipantContextCreated created && created.getParticipantId().equals(manifest.getParticipantId())));
verify(subscriber, times(1)).on(argThat(evt -> evt.getPayload() instanceof DidDocumentPublished));

assertThat(context.getKeyPairsForParticipant(manifest.getParticipantId())).hasSize(1)
.allSatisfy(kpr -> assertThat(kpr.getState()).isEqualTo(KeyPairState.ACTIVATED.code()));
Expand Down

0 comments on commit db0206e

Please sign in to comment.