diff --git a/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/PartyInfoResource.java b/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/PartyInfoResource.java new file mode 100644 index 0000000000..b70b55f879 --- /dev/null +++ b/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/PartyInfoResource.java @@ -0,0 +1,53 @@ +package com.quorum.tessera.thirdparty; + +import com.quorum.tessera.partyinfo.PartyInfoService; +import com.quorum.tessera.partyinfo.model.PartyInfo; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import static java.util.Objects.requireNonNull; + +@Path("/partyinfo") +public class PartyInfoResource { + + private final PartyInfoService partyInfoService; + + public PartyInfoResource(final PartyInfoService partyInfoService) { + this.partyInfoService = requireNonNull(partyInfoService, "partyInfoService must not be null"); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Fetch network/peer information", produces = "public list of peers/publickey mappings") + @ApiResponses({@ApiResponse(code = 200, message = "Peer/Network information", response = PartyInfo.class)}) + public Response getPartyInfo() { + + final PartyInfo current = this.partyInfoService.getPartyInfo(); + + final JsonArrayBuilder recipientBuilder = Json.createArrayBuilder(); + current.getRecipients().stream() + .map( + recipient -> + Json.createObjectBuilder() + .add("key", recipient.getKey().encodeToBase64()) + .build()) + .forEach(recipientBuilder::add); + + final String output = + Json.createObjectBuilder() + .add("keys", recipientBuilder.build()) + .build() + .toString(); + + return Response.status(Response.Status.OK).entity(output).build(); + } +} diff --git a/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/ThirdPartyRestApp.java b/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/ThirdPartyRestApp.java index 758ca40ea9..ef2a0a5b8e 100644 --- a/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/ThirdPartyRestApp.java +++ b/tessera-jaxrs/thirdparty-jaxrs/src/main/java/com/quorum/tessera/thirdparty/ThirdPartyRestApp.java @@ -3,6 +3,9 @@ import com.quorum.tessera.api.filter.IPWhitelistFilter; import com.quorum.tessera.app.TesseraRestApplication; import com.quorum.tessera.config.AppType; +import com.quorum.tessera.core.api.ServiceFactory; +import com.quorum.tessera.partyinfo.PartyInfoService; + import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -13,13 +16,21 @@ @ApplicationPath("/") public class ThirdPartyRestApp extends TesseraRestApplication { + private final PartyInfoService partyInfoService; + + public ThirdPartyRestApp() { + final ServiceFactory serviceFactory = ServiceFactory.create(); + this.partyInfoService = serviceFactory.partyInfoService(); + } + @Override public Set getSingletons() { - IPWhitelistFilter iPWhitelistFilter = new IPWhitelistFilter(); - RawTransactionResource rawTransactionResource = new RawTransactionResource(); + final IPWhitelistFilter iPWhitelistFilter = new IPWhitelistFilter(); + final RawTransactionResource rawTransactionResource = new RawTransactionResource(); + final PartyInfoResource partyInfoResource = new PartyInfoResource(partyInfoService); - return Stream.of(iPWhitelistFilter, rawTransactionResource).collect(Collectors.toSet()); + return Stream.of(iPWhitelistFilter, rawTransactionResource, partyInfoResource).collect(Collectors.toSet()); } @Override diff --git a/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/PartyInfoResourceTest.java b/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/PartyInfoResourceTest.java new file mode 100644 index 0000000000..522b364b70 --- /dev/null +++ b/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/PartyInfoResourceTest.java @@ -0,0 +1,86 @@ +package com.quorum.tessera.thirdparty; + +import com.quorum.tessera.encryption.PublicKey; +import com.quorum.tessera.partyinfo.PartyInfoService; +import com.quorum.tessera.partyinfo.model.Party; +import com.quorum.tessera.partyinfo.model.PartyInfo; +import com.quorum.tessera.partyinfo.model.Recipient; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.json.Json; +import javax.json.JsonReader; +import javax.ws.rs.core.Response; +import java.io.StringReader; +import java.time.Instant; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +public class PartyInfoResourceTest { + + private PartyInfoService partyInfoService; + + private PartyInfoResource partyInfoResource; + + @Before + public void onSetup() { + this.partyInfoService = mock(PartyInfoService.class); + + this.partyInfoResource = new PartyInfoResource(partyInfoService); + } + + @After + public void onTearDown() { + verifyNoMoreInteractions(partyInfoService); + } + + @Test + public void partyInfoGet() { + + final String partyInfoJson = + "{\"keys\":[{\"key\":\"BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=\"},{\"key\":\"QfeDAys9MPDs2XHExtc84jKGHxZg/aj52DTh0vtA3Xc=\"}]}"; + + final Party partyWithoutTimestamp = new Party("http://localhost:9006/"); + final Party partyWithTimestamp = new Party("http://localhost:9005/"); + partyWithTimestamp.setLastContacted(Instant.parse("2019-01-02T15:03:22.875Z")); + + final PartyInfo partyInfo = + new PartyInfo( + "http://localhost:9001/", + new HashSet<>( + Arrays.asList( + new Recipient( + PublicKey.from( + Base64.getDecoder() + .decode( + "BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=")), + "http://localhost:9001/"), + new Recipient( + PublicKey.from( + Base64.getDecoder() + .decode( + "QfeDAys9MPDs2XHExtc84jKGHxZg/aj52DTh0vtA3Xc=")), + "http://localhost:9002/"))), + new HashSet<>(Arrays.asList(partyWithTimestamp, partyWithoutTimestamp))); + + when(partyInfoService.getPartyInfo()).thenReturn(partyInfo); + + final Response response = partyInfoResource.getPartyInfo(); + + assertThat(response).isNotNull(); + assertThat(response.getStatus()).isEqualTo(200); + + final String output = response.getEntity().toString(); + final JsonReader expected = Json.createReader(new StringReader(partyInfoJson)); + final JsonReader actual = Json.createReader(new StringReader(output)); + + assertThat(expected.readObject()).isEqualTo(actual.readObject()); + + verify(partyInfoService).getPartyInfo(); + } +} diff --git a/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/ThirdPartyRestAppTest.java b/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/ThirdPartyRestAppTest.java index e1a60a37ac..a8bc82a763 100644 --- a/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/ThirdPartyRestAppTest.java +++ b/tessera-jaxrs/thirdparty-jaxrs/src/test/java/com/quorum/tessera/thirdparty/ThirdPartyRestAppTest.java @@ -1,9 +1,9 @@ package com.quorum.tessera.thirdparty; -import com.quorum.tessera.thirdparty.ThirdPartyRestApp; import com.jpmorgan.quorum.mock.servicelocator.MockServiceLocator; import com.quorum.tessera.admin.ConfigService; import com.quorum.tessera.config.AppType; +import com.quorum.tessera.partyinfo.PartyInfoService; import com.quorum.tessera.service.locator.ServiceLocator; import com.quorum.tessera.transaction.TransactionManager; import java.util.HashSet; @@ -34,6 +34,7 @@ public void setUp() throws Exception { Set services = new HashSet(); services.add(mock(ConfigService.class)); services.add(mock(TransactionManager.class)); + services.add(mock(PartyInfoService.class)); serviceLocator.setServices(services); @@ -62,7 +63,7 @@ public void getSingletons() { Set results = thirdParty.getSingletons(); - assertThat(results).hasSize(2); + assertThat(results).hasSize(3); } @Test