Skip to content

Commit

Permalink
feat: add get-all endpoints for MgmgApi (#267)
Browse files Browse the repository at this point in the history
* feat: add Get-All endpoints for all APIs

* upgrade to gradle 8.6

* DEPENDENCIES
  • Loading branch information
paullatzelsperger authored Feb 12, 2024
1 parent f892239 commit 442467d
Show file tree
Hide file tree
Showing 34 changed files with 733 additions and 50 deletions.
11 changes: 4 additions & 7 deletions DEPENDENCIES
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,10 @@ maven/mavencentral/org.hamcrest/hamcrest-core/1.3, BSD-2-Clause, approved, CQ114
maven/mavencentral/org.hamcrest/hamcrest-core/2.2, BSD-3-Clause, approved, clearlydefined
maven/mavencentral/org.hamcrest/hamcrest/2.1, BSD-3-Clause, approved, clearlydefined
maven/mavencentral/org.hamcrest/hamcrest/2.2, BSD-3-Clause, approved, clearlydefined
maven/mavencentral/org.jacoco/org.jacoco.agent/0.8.9, EPL-2.0, approved, CQ23285
maven/mavencentral/org.jacoco/org.jacoco.ant/0.8.9, EPL-2.0, approved, #1068
maven/mavencentral/org.jacoco/org.jacoco.core/0.8.9, EPL-2.0, approved, CQ23283
maven/mavencentral/org.jacoco/org.jacoco.report/0.8.9, EPL-2.0 AND Apache-2.0, approved, CQ23284
maven/mavencentral/org.jacoco/org.jacoco.agent/0.8.11, EPL-2.0, approved, CQ23285
maven/mavencentral/org.jacoco/org.jacoco.ant/0.8.11, EPL-2.0, approved, #1068
maven/mavencentral/org.jacoco/org.jacoco.core/0.8.11, EPL-2.0, approved, CQ23283
maven/mavencentral/org.jacoco/org.jacoco.report/0.8.11, EPL-2.0 AND Apache-2.0, approved, CQ23284
maven/mavencentral/org.javassist/javassist/3.28.0-GA, Apache-2.0 OR LGPL-2.1-or-later OR MPL-1.1, approved, #327
maven/mavencentral/org.javassist/javassist/3.29.2-GA, Apache-2.0 AND LGPL-2.1-or-later AND MPL-1.1, approved, #6023
maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.10, Apache-2.0, approved, clearlydefined
Expand Down Expand Up @@ -360,12 +360,9 @@ maven/mavencentral/org.mockito/mockito-core/5.9.0, MIT AND (Apache-2.0 AND MIT)
maven/mavencentral/org.mozilla/rhino/1.7.7.2, MPL-2.0 AND BSD-3-Clause AND ISC, approved, CQ16320
maven/mavencentral/org.objenesis/objenesis/3.3, Apache-2.0, approved, clearlydefined
maven/mavencentral/org.opentest4j/opentest4j/1.3.0, Apache-2.0, approved, #9713
maven/mavencentral/org.ow2.asm/asm-commons/9.5, BSD-3-Clause, approved, #7553
maven/mavencentral/org.ow2.asm/asm-commons/9.6, BSD-3-Clause, approved, #10775
maven/mavencentral/org.ow2.asm/asm-tree/9.5, BSD-3-Clause, approved, #7555
maven/mavencentral/org.ow2.asm/asm-tree/9.6, BSD-3-Clause, approved, #10773
maven/mavencentral/org.ow2.asm/asm/9.1, BSD-3-Clause, approved, CQ23029
maven/mavencentral/org.ow2.asm/asm/9.5, BSD-3-Clause, approved, #7554
maven/mavencentral/org.ow2.asm/asm/9.6, BSD-3-Clause, approved, #10776
maven/mavencentral/org.postgresql/postgresql/42.7.1, BSD-2-Clause AND Apache-2.0, approved, #11681
maven/mavencentral/org.reflections/reflections/0.10.2, Apache-2.0 AND WTFPL, approved, clearlydefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@Path("/participants/{participantId}/presentation")
@Path("/v1/participants/{participantId}/presentation")
public class PresentationApiController implements PresentationApi {

private final JsonObjectValidatorRegistry validatorRegistry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ public ServiceResult<Void> removeService(String did, String serviceId) {
@Override
public <E extends Event> void on(EventEnvelope<E> eventEnvelope) {
var payload = eventEnvelope.getPayload();
monitor.debug("Received a [%s] event".formatted(payload.getClass().getSimpleName()));
if (payload instanceof ParticipantContextUpdated event) {
updated(event);
} else if (payload instanceof ParticipantContextDeleted event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ public ServiceResult<Collection<KeyPairResource>> query(QuerySpec querySpec) {
@Override
public <E extends Event> void on(EventEnvelope<E> eventEnvelope) {
var payload = eventEnvelope.getPayload();
monitor.debug("Received a [%s] event".formatted(payload.getClass().getSimpleName()));
if (payload instanceof ParticipantContextDeleted deleted) {
deleted(deleted);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.edc.spi.security.Vault;
import org.eclipse.edc.transaction.spi.TransactionContext;

import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;

Expand Down Expand Up @@ -126,6 +127,11 @@ public ServiceResult<Void> updateParticipant(String participantId, Consumer<Part

}

@Override
public ServiceResult<Collection<ParticipantContext>> query(QuerySpec querySpec) {
return transactionContext.execute(() -> ServiceResult.from(participantContextStore.query(querySpec)));
}

private ServiceResult<String> createTokenAndStoreInVault(ParticipantContext participantContext) {
var alias = participantContext.getApiTokenAlias();
var newToken = tokenGenerator.generate(participantContext.getParticipantId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.edc.identityhub.spi.model.participant.ParticipantContextState;
import org.eclipse.edc.identityhub.spi.model.participant.ParticipantManifest;
import org.eclipse.edc.identityhub.spi.store.ParticipantContextStore;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.result.ServiceFailure;
import org.eclipse.edc.spi.result.StoreResult;
Expand Down Expand Up @@ -295,6 +296,22 @@ void update_whenStoreUpdateFails() {
verifyNoMoreInteractions(participantContextStore, observableMock);
}

@Test
void query() {
var ctx = createContext();
when(participantContextStore.query(any())).thenReturn(StoreResult.success(List.of(
createContext(),
createContext(),
createContext())));

assertThat(participantContextService.query(QuerySpec.max()))
.isSucceeded()
.satisfies(res -> Assertions.assertThat(res).hasSize(3));

verify(participantContextStore).query(any());
verifyNoMoreInteractions(vault);
}

private ParticipantManifest.Builder createManifest() {
return ParticipantManifest.Builder.newInstance()
.key(createKey().build())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.eclipse.edc.identityhub.tests;

import io.restassured.http.Header;
import org.eclipse.edc.iam.did.spi.document.DidDocument;
import org.eclipse.edc.identityhub.spi.events.diddocument.DidDocumentPublished;
import org.eclipse.edc.identityhub.spi.events.diddocument.DidDocumentUnpublished;
import org.eclipse.edc.identityhub.spi.model.participant.ParticipantContext;
Expand All @@ -27,6 +28,7 @@
import java.util.Arrays;

import static io.restassured.http.ContentType.JSON;
import static java.util.stream.IntStream.range;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -210,4 +212,65 @@ void getState_nowOwner_expect403() {
.statusCode(403);
}

@Test
void getAll() {
range(0, 20).forEach(i -> createParticipant("user-" + i));

var docs = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/dids")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(DidDocument[].class);

assertThat(docs).hasSize(21); //includes the super-user's DID doc
}

@Test
void getAll_withDefaultPaging() {
range(0, 70).forEach(i -> createParticipant("user-" + i));

var docs = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/dids")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(DidDocument[].class);

assertThat(docs).hasSize(50); //includes the super-user's DID doc
}

@Test
void getAll_withPaging() {
range(0, 20).forEach(i -> createParticipant("user-" + i));

var docs = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/dids?offset=5&limit=10")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(DidDocument[].class);

assertThat(docs).hasSize(10);
}

@Test
void getAll_notAuthorized() {

var attackerToken = createParticipant("attacker");

RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", attackerToken))
.get("/v1/dids")
.then()
.log().ifValidationFails()
.statusCode(403);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;

import static io.restassured.http.ContentType.JSON;
import static java.util.stream.IntStream.range;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.ArgumentMatchers.argThat;
Expand Down Expand Up @@ -335,6 +337,78 @@ void revoke_notAuthorized() {
.body(notNullValue());
}

@Test
void getAll() {
range(0, 10)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
var found = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/keypairs")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(KeyPairResource[].class);
assertThat(found).hasSize(11); //10 + 1 for the super user
}

@Test
void getAll_withPaging() {
range(0, 10)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
var found = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/keypairs?offset=2&limit=4")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(KeyPairResource[].class);
assertThat(found).hasSize(4);
}

@Test
void getAll_withDefaultPaging() {
IntStream.range(0, 70)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
var found = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/keypairs")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(KeyPairResource[].class);
assertThat(found).hasSize(50);
}

@Test
void getAll_notAuthorized() {
var attackerToken = createParticipant("attacker");

range(0, 10)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", attackerToken))
.get("/v1/keypairs")
.then()
.log().ifValidationFails()
.statusCode(403);
}

private String createKeyPair(String participantId) {

var descriptor = createKeyDescriptor(participantId).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@

import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;

import static io.restassured.http.ContentType.JSON;
import static java.util.stream.IntStream.range;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.equalTo;
Expand Down Expand Up @@ -260,4 +263,75 @@ void updateRoles_whenNotSuperuser(String role) {
.statusCode(403);
}

@Test
void getAll() {
range(0, 10)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId);
});
var found = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/participants")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(ParticipantContext[].class);
assertThat(found).hasSize(11); //10 + 1 for the super user
}

@Test
void getAll_withPaging() {
range(0, 10)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
var found = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/participants?offset=2&limit=4")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(ParticipantContext[].class);
assertThat(found).hasSize(4);
}

@Test
void getAll_withDefaultPaging() {
IntStream.range(0, 70)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
var found = RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", getSuperUserApiKey()))
.get("/v1/participants")
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().body().as(ParticipantContext[].class);
assertThat(found).hasSize(50);
}

@Test
void getAll_notAuthorized() {
var attackerToken = createParticipant("attacker");

range(0, 10)
.forEach(i -> {
var participantId = "user" + i;
createParticipant(participantId); // implicitly creates a keypair
});
RUNTIME_CONFIGURATION.getManagementEndpoint().baseRequest()
.contentType(JSON)
.header(new Header("x-api-key", attackerToken))
.get("/v1/participants")
.then()
.log().ifValidationFails()
.statusCode(403);
}
}
Loading

0 comments on commit 442467d

Please sign in to comment.