Skip to content
This repository has been archived by the owner on Dec 22, 2021. It is now read-only.

Retrieve privacy group endpoint #307

Merged
merged 18 commits into from
Dec 8, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions gradle/versions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ dependencyManagement {

dependency 'org.fusesource.leveldbjni:leveldbjni-all:1.8'

dependency 'org.junit.jupiter:junit-jupiter-api:5.2.0'
dependency 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
dependency 'org.junit.jupiter:junit-jupiter-params:5.2.0'
dependency 'org.junit.jupiter:junit-jupiter-api:5.5.2'
dependency 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
dependency 'org.junit.jupiter:junit-jupiter-params:5.5.2'

dependency 'org.mapdb:mapdb:3.0.7'
dependency 'org.lz4:lz4-java:1.6.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import net.consensys.orion.http.handler.privacy.FindPrivacyGroupRequest;
import net.consensys.orion.http.handler.privacy.PrivacyGroup;
import net.consensys.orion.http.handler.privacy.PrivacyGroupRequest;
import net.consensys.orion.http.handler.privacy.RetrievePrivacyGroupRequest;
import net.consensys.orion.http.handler.receive.ReceiveRequest;
import net.consensys.orion.http.handler.receive.ReceiveResponse;
import net.consensys.orion.utils.Serializer;
Expand Down Expand Up @@ -172,6 +173,20 @@ public Optional<PrivacyGroup[]> findPrivacyGroup(final String[] addresses) {
return Optional.ofNullable(keyFuture.join());
}

public Optional<PrivacyGroup> retrievePrivacyGroup(final String privacyGroupId) {
final RetrievePrivacyGroupRequest getGroupRequest = new RetrievePrivacyGroupRequest(privacyGroupId);
final CompletableFuture<PrivacyGroup> keyFuture = new CompletableFuture<>();
httpClient.post(clientPort, "localhost", "/retrievePrivacyGroup").handler(resp -> {
if (resp.statusCode() == 200) {
resp.bodyHandler(body -> keyFuture.complete(deserialize(body, PrivacyGroup.class)));
} else {
keyFuture.complete(null);
}
}).exceptionHandler(keyFuture::completeExceptionally).putHeader("Content-Type", "application/json").end(
Buffer.buffer(Serializer.serialize(JSON, getGroupRequest)));
return Optional.ofNullable(keyFuture.join());
jframe marked this conversation as resolved.
Show resolved Hide resolved
}

public Optional<String> deletePrivacyGroup(final String privacyGroupId, final String from) {
final DeletePrivacyGroupRequest deleteGroupRequest = new DeletePrivacyGroupRequest(privacyGroupId, from);
final CompletableFuture<String> keyFuture = new CompletableFuture<>();
Expand Down Expand Up @@ -214,4 +229,5 @@ private Map<String, Object> sendRequest(final byte[] payload, final String from,
map.put("privacyGroupId", privacyGroupId);
return map;
}

jframe marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ public static String deletePrivacyGroupTransaction(
return sender.deletePrivacyGroup(privacyGroupId, from).orElseThrow(AssertionFailedError::new);
}

public static PrivacyGroup retrievePrivacyGroupTransaction(final EthClientStub sender, final String privacyGroupId) {
return sender.retrievePrivacyGroup(privacyGroupId).orElseThrow(AssertionFailedError::new);
}

/** Asserts the received payload matches that sent. */
public static void assertTransaction(final byte[] receivedPayload) {
assertArrayEquals(originalPayload, receivedPayload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,12 @@ void setUp(@TempDirectory final Path tempDir) throws Exception {

@AfterEach
void tearDown() {
orionLauncher.stop();
vertx.close();
if (orionLauncher != null) {
orionLauncher.stop();
}
if (vertx != null) {
vertx.close();
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,12 @@ void setUp(@TempDirectory final Path tempDir) throws Exception {

@AfterEach
void tearDown() {
orionLauncher.stop();
vertx.close();
if (orionLauncher != null) {
orionLauncher.stop();
}
if (vertx != null) {
vertx.close();
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
import static net.consensys.orion.acceptance.NodeUtils.deletePrivacyGroupTransaction;
import static net.consensys.orion.acceptance.NodeUtils.findPrivacyGroupTransaction;
import static net.consensys.orion.acceptance.NodeUtils.joinPathsAsTomlListEntry;
import static net.consensys.orion.acceptance.NodeUtils.retrievePrivacyGroupTransaction;
import static net.consensys.orion.http.server.HttpContentType.CBOR;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;

import net.consensys.cava.crypto.sodium.Box;
import net.consensys.cava.junit.TempDirectory;
import net.consensys.cava.junit.TempDirectoryExtension;
import net.consensys.orion.acceptance.EthClientStub;
import net.consensys.orion.acceptance.NodeUtils;
Expand Down Expand Up @@ -60,6 +61,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;

/** Runs up a two nodes that communicates with each other. */
@ExtendWith(TempDirectoryExtension.class)
Expand All @@ -68,18 +70,14 @@ class DualNodesPrivacyGroupsTest {
private static final String PK_1_B_64 = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final String PK_2_B_64 = "Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=";

private Config firstNodeConfig;
private Config secondNodeConfig;
private ConcurrentNetworkNodes networkNodes;

private Orion firstOrionLauncher;
private Orion secondOrionLauncher;
private Vertx vertx;
private HttpClient firstHttpClient;
private HttpClient secondHttpClient;

@BeforeEach
void setUpDualNodes(@TempDirectory final Path tempDir) throws Exception {
void setUpDualNodes(@TempDir final Path tempDir) throws Exception {

final Path key1pub = copyResource("key1.pub", tempDir.resolve("key1.pub"));
final Path key1key = copyResource("key1.key", tempDir.resolve("key1.key"));
Expand All @@ -91,7 +89,7 @@ void setUpDualNodes(@TempDirectory final Path tempDir) throws Exception {
st.executeUpdate("create table if not exists store(key char(60), value binary, primary key(key))");
}

firstNodeConfig = NodeUtils.nodeConfig(
final Config firstNodeConfig = NodeUtils.nodeConfig(
tempDir,
0,
"127.0.0.1",
Expand All @@ -104,7 +102,7 @@ void setUpDualNodes(@TempDirectory final Path tempDir) throws Exception {
"tofu",
"tofu",
"leveldb:database/node1");
secondNodeConfig = NodeUtils.nodeConfig(
final Config secondNodeConfig = NodeUtils.nodeConfig(
tempDir,
0,
"127.0.0.1",
Expand All @@ -125,7 +123,8 @@ void setUpDualNodes(@TempDirectory final Path tempDir) throws Exception {
secondHttpClient = vertx.createHttpClient();
final Box.PublicKey pk1 = Box.PublicKey.fromBytes(decodeBytes(PK_1_B_64));
final Box.PublicKey pk2 = Box.PublicKey.fromBytes(decodeBytes(PK_2_B_64));
networkNodes = new ConcurrentNetworkNodes(NodeUtils.url("127.0.0.1", firstOrionLauncher.nodePort()));
final ConcurrentNetworkNodes networkNodes =
new ConcurrentNetworkNodes(NodeUtils.url("127.0.0.1", firstOrionLauncher.nodePort()));

networkNodes.addNode(Collections.singletonList(pk1), NodeUtils.url("127.0.0.1", firstOrionLauncher.nodePort()));
networkNodes.addNode(Collections.singletonList(pk2), NodeUtils.url("127.0.0.1", secondOrionLauncher.nodePort()));
Expand All @@ -147,13 +146,11 @@ private ConcurrentNetworkNodes getPartyInfoResponse(final OkHttpClient httpClien
final Response resp = httpClient.newCall(request).execute();
assertEquals(200, resp.code());

final ConcurrentNetworkNodes partyInfoResponse =
Serializer.deserialize(HttpContentType.CBOR, ConcurrentNetworkNodes.class, resp.body().bytes());
return partyInfoResponse;
return Serializer.deserialize(HttpContentType.CBOR, ConcurrentNetworkNodes.class, resp.body().bytes());
}

@AfterEach
void tearDown() throws InterruptedException {
void tearDown() {
await().atMost(5, TimeUnit.SECONDS).until(() -> doesNotThrowWhenCallingStop(firstOrionLauncher));
await().atMost(5, TimeUnit.SECONDS).until(() -> doesNotThrowWhenCallingStop(secondOrionLauncher));
vertx.close();
Expand Down Expand Up @@ -197,6 +194,38 @@ void createAndFind() {
firstNodePrivacyGroups[0].getPrivacyGroupId());
}

@Test
void createAndRetrieve() {
final EthClientStub firstNode = NodeUtils.client(firstOrionLauncher.clientPort(), firstHttpClient);
final EthClientStub secondNode = NodeUtils.client(secondOrionLauncher.clientPort(), secondHttpClient);

final String name = "testName";
final String description = "testDescription";
final String[] addresses = new String[] {PK_1_B_64, PK_2_B_64};
// create a privacy group
final PrivacyGroup privacyGroup = createPrivacyGroupTransaction(firstNode, addresses, PK_1_B_64, name, description);

final String privacyGroupId = privacyGroup.getPrivacyGroupId();
assertEquals(privacyGroup.getName(), name);
assertEquals(privacyGroup.getDescription(), description);

// get the created privacy group in first node
final PrivacyGroup firstNodePrivacyGroup = retrievePrivacyGroupTransaction(firstNode, privacyGroupId);

assertEquals(firstNodePrivacyGroup.getPrivacyGroupId(), privacyGroupId);
assertEquals(firstNodePrivacyGroup.getDescription(), description);
assertEquals(firstNodePrivacyGroup.getName(), name);
assertArrayEquals(firstNodePrivacyGroup.getMembers(), addresses);

// get the created privacy group in second node
await().atMost(20, TimeUnit.SECONDS).until(
() -> retrievePrivacyGroupTransaction(secondNode, privacyGroupId).getPrivacyGroupId().equals(privacyGroupId));
final PrivacyGroup secondNodePrivacyGroup = retrievePrivacyGroupTransaction(secondNode, privacyGroupId);
assertEquals(secondNodePrivacyGroup.getDescription(), description);
jframe marked this conversation as resolved.
Show resolved Hide resolved
assertEquals(secondNodePrivacyGroup.getName(), name);
assertArrayEquals(secondNodePrivacyGroup.getMembers(), addresses);
}

@Test
void createDeleteFind() {
final EthClientStub firstNode = NodeUtils.client(firstOrionLauncher.clientPort(), firstHttpClient);
Expand Down Expand Up @@ -230,7 +259,6 @@ void createDeleteFind() {
assertFalse(listSecond.contains(privacyGroupDeleted));
}


@Test
void createTwiceDeleteOnce() {
final EthClientStub firstNode = NodeUtils.client(firstOrionLauncher.clientPort(), firstHttpClient);
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/net/consensys/orion/cmd/Orion.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import net.consensys.orion.http.handler.privacy.CreatePrivacyGroupHandler;
import net.consensys.orion.http.handler.privacy.DeletePrivacyGroupHandler;
import net.consensys.orion.http.handler.privacy.FindPrivacyGroupHandler;
import net.consensys.orion.http.handler.privacy.RetrievePrivacyGroupHandler;
import net.consensys.orion.http.handler.push.PushHandler;
import net.consensys.orion.http.handler.push.PushPrivacyGroupHandler;
import net.consensys.orion.http.handler.receive.ReceiveHandler;
Expand Down Expand Up @@ -212,6 +213,9 @@ public static void configureRoutes(
clientRouter.post("/findPrivacyGroup").consumes(JSON.httpHeaderValue).produces(JSON.httpHeaderValue).handler(
new FindPrivacyGroupHandler(queryPrivacyGroupStorage, privacyGroupStorage));

clientRouter.post("/retrievePrivacyGroup").consumes(JSON.httpHeaderValue).produces(JSON.httpHeaderValue).handler(
new RetrievePrivacyGroupHandler(privacyGroupStorage));

clientRouter.get("/knownnodes").produces(JSON.httpHeaderValue).handler(new KnownNodesHandler(networkNodes));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2019 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package net.consensys.orion.http.handler.privacy;

import static net.consensys.orion.http.server.HttpContentType.JSON;

import net.consensys.orion.enclave.PrivacyGroupPayload;
import net.consensys.orion.enclave.PrivacyGroupPayload.State;
import net.consensys.orion.exception.OrionErrorCode;
import net.consensys.orion.exception.OrionException;
import net.consensys.orion.storage.Storage;
import net.consensys.orion.utils.Serializer;

import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.RoutingContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* Retrieves a privacy group given the privacyGroupId.
*/
public class RetrievePrivacyGroupHandler implements Handler<RoutingContext> {

private static final Logger log = LogManager.getLogger();

private final Storage<PrivacyGroupPayload> privacyGroupStorage;

public RetrievePrivacyGroupHandler(final Storage<PrivacyGroupPayload> privacyGroupStorage) {
this.privacyGroupStorage = privacyGroupStorage;
}

@Override
@SuppressWarnings("rawtypes")
public void handle(final RoutingContext routingContext) {
final byte[] request = routingContext.getBody().getBytes();
final RetrievePrivacyGroupRequest retrievePrivacyGroupRequest =
Serializer.deserialize(JSON, RetrievePrivacyGroupRequest.class, request);

final String privacyGroupId = retrievePrivacyGroupRequest.privacyGroupId();

if (privacyGroupId == null) {
routingContext.fail(400);
} else {
handleRequest(routingContext, privacyGroupId);
}
}

private void handleRequest(final RoutingContext routingContext, final String privacyGroupId) {
privacyGroupStorage.get(privacyGroupId).thenAccept((result) -> {
if (result.isPresent()) {
final PrivacyGroupPayload privacyGroupPayload = result.get();
log.info("Found privacy group {}", privacyGroupId);
if (privacyGroupPayload.state().equals(State.ACTIVE)) {
privacyGroupResponse(routingContext, privacyGroupId, privacyGroupPayload);
} else {
notFoundResponse(routingContext);
}
} else {
notFoundResponse(routingContext);
}
});
}

private void privacyGroupResponse(
jframe marked this conversation as resolved.
Show resolved Hide resolved
final RoutingContext routingContext,
final String privacyGroupId,
final PrivacyGroupPayload privacyGroupPayload) {
final PrivacyGroup response = new PrivacyGroup(
privacyGroupId,
privacyGroupPayload.type(),
privacyGroupPayload.name(),
privacyGroupPayload.description(),
privacyGroupPayload.addresses());
routingContext.response().end(Buffer.buffer(Serializer.serialize(JSON, response)));
}

private void notFoundResponse(final RoutingContext routingContext) {
routingContext.fail(404, new OrionException(OrionErrorCode.ENCLAVE_PRIVACY_GROUP_MISSING));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2019 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package net.consensys.orion.http.handler.privacy;

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class RetrievePrivacyGroupRequest implements Serializable {

private final String privacyGroupId;

@JsonCreator
public RetrievePrivacyGroupRequest(@JsonProperty("privacyGroupId") final String privacyGroupId) {
this.privacyGroupId = privacyGroupId;
}

@JsonProperty("privacyGroupId")
public String privacyGroupId() {
return privacyGroupId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
@ExtendWith(TempDirectoryExtension.class)
public abstract class HandlerTest {

static final String RETRIEVE_PRIVACY_GROUP = "/retrievePrivacyGroup";
static final String DELETE_PRIVACY_GROUP = "/deletePrivacyGroup";
static final String PUSH_PRIVACY_GROUP = "/pushPrivacyGroup";
static final String CREATE_PRIVACY_GROUP = "/createPrivacyGroup";

// http client
protected final OkHttpClient httpClient = new OkHttpClient();
protected String nodeBaseUrl;
Expand Down
Loading