mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Add mailbox API endpoint for adding a contact
This commit is contained in:
@@ -31,6 +31,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -46,6 +47,7 @@ import static org.briarproject.bramble.api.sync.ClientId.MAX_CLIENT_ID_LENGTH;
|
||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
|
||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||
|
||||
public class TestUtils {
|
||||
|
||||
@@ -209,6 +211,10 @@ public class TestUtils {
|
||||
getAgreementPublicKey(), verified);
|
||||
}
|
||||
|
||||
public static String getMailboxSecret() {
|
||||
return toHexString(getRandomBytes(32)).toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
public static double getMedian(Collection<? extends Number> samples) {
|
||||
int size = samples.size();
|
||||
if (size == 0) throw new IllegalArgumentException();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -27,7 +28,41 @@ interface MailboxApi {
|
||||
boolean checkStatus(MailboxProperties properties)
|
||||
throws IOException, PermanentFailureException;
|
||||
|
||||
/**
|
||||
* Adds a new contact to the mailbox.
|
||||
*
|
||||
* @throws TolerableFailureException if response code is 409
|
||||
* (contact was already added).
|
||||
*/
|
||||
void addContact(MailboxProperties properties, MailboxContact contact)
|
||||
throws IOException, PermanentFailureException,
|
||||
TolerableFailureException;
|
||||
|
||||
@Immutable
|
||||
class MailboxContact {
|
||||
public final int contactId;
|
||||
public final String token, inboxId, outboxId;
|
||||
|
||||
MailboxContact(ContactId contactId,
|
||||
String token,
|
||||
String inboxId,
|
||||
String outboxId) {
|
||||
this.contactId = contactId.getInt();
|
||||
this.token = token;
|
||||
this.inboxId = inboxId;
|
||||
this.outboxId = outboxId;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
class PermanentFailureException extends Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* A failure that does not need to be retried,
|
||||
* e.g. when adding a contact that already exists.
|
||||
*/
|
||||
@Immutable
|
||||
class TolerableFailureException extends Exception {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,15 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import static com.fasterxml.jackson.databind.MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static okhttp3.internal.Util.EMPTY_REQUEST;
|
||||
import static org.briarproject.bramble.util.StringUtils.fromHexString;
|
||||
|
||||
@@ -28,6 +31,8 @@ class MailboxApiImpl implements MailboxApi {
|
||||
private final JsonMapper mapper = JsonMapper.builder()
|
||||
.enable(BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES)
|
||||
.build();
|
||||
private static final MediaType JSON =
|
||||
requireNonNull(MediaType.parse("application/json; charset=utf-8"));
|
||||
|
||||
@Inject
|
||||
MailboxApiImpl(WeakSingletonProvider<OkHttpClient> httpClientProvider) {
|
||||
@@ -89,6 +94,23 @@ class MailboxApiImpl implements MailboxApi {
|
||||
return response.isSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContact(MailboxProperties properties, MailboxContact contact)
|
||||
throws IOException, PermanentFailureException,
|
||||
TolerableFailureException {
|
||||
if (!properties.isOwner()) throw new IllegalArgumentException();
|
||||
byte[] bodyBytes = mapper.writeValueAsBytes(contact);
|
||||
RequestBody body = RequestBody.create(JSON, bodyBytes);
|
||||
Request request = getRequestBuilder(properties.getAuthToken())
|
||||
.url(properties.getOnionAddress() + "/contacts")
|
||||
.post(body)
|
||||
.build();
|
||||
OkHttpClient client = httpClientProvider.get();
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.code() == 409) throw new TolerableFailureException();
|
||||
if (!response.isSuccessful()) throw new IOException();
|
||||
}
|
||||
|
||||
private Request.Builder getRequestBuilder(String token) {
|
||||
return new Request.Builder()
|
||||
.addHeader("Authorization", "Bearer " + token);
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.WeakSingletonProvider;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||
import org.briarproject.bramble.mailbox.MailboxApi.MailboxContact;
|
||||
import org.briarproject.bramble.mailbox.MailboxApi.PermanentFailureException;
|
||||
import org.briarproject.bramble.mailbox.MailboxApi.TolerableFailureException;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
@@ -15,9 +20,9 @@ import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.bramble.test.TestUtils.getContactId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMailboxSecret;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -40,8 +45,14 @@ public class MailboxApiTest extends BrambleTestCase {
|
||||
};
|
||||
private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider);
|
||||
|
||||
private final String token = toHexString(getRandomBytes(32));
|
||||
private final String token2 = toHexString(getRandomBytes(32));
|
||||
private final String token = getMailboxSecret();
|
||||
private final String token2 = getMailboxSecret();
|
||||
private final ContactId contactId = getContactId();
|
||||
private final String contactToken = getMailboxSecret();
|
||||
private final String contactInboxId = getMailboxSecret();
|
||||
private final String contactOutboxId = getMailboxSecret();
|
||||
private final MailboxContact mailboxContact = new MailboxContact(
|
||||
contactId, contactToken, contactInboxId, contactOutboxId);
|
||||
|
||||
@Test
|
||||
public void testSetup() throws Exception {
|
||||
@@ -175,6 +186,52 @@ public class MailboxApiTest extends BrambleTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddContact() throws Exception {
|
||||
MockWebServer server = new MockWebServer();
|
||||
server.enqueue(new MockResponse());
|
||||
server.enqueue(new MockResponse().setResponseCode(401));
|
||||
server.enqueue(new MockResponse().setResponseCode(409));
|
||||
server.start();
|
||||
String baseUrl = getBaseUrl(server);
|
||||
MailboxProperties properties =
|
||||
new MailboxProperties(baseUrl, token, true);
|
||||
|
||||
// contact gets added as expected
|
||||
api.addContact(properties, mailboxContact);
|
||||
RecordedRequest request1 = server.takeRequest();
|
||||
assertEquals("/contacts", request1.getPath());
|
||||
assertToken(request1, token);
|
||||
String expected = "{\"contactId\":" + contactId.getInt() +
|
||||
",\"token\":\"" + contactToken +
|
||||
"\",\"inboxId\":\"" + contactInboxId +
|
||||
"\",\"outboxId\":\"" + contactOutboxId +
|
||||
"\"}";
|
||||
assertEquals(expected, request1.getBody().readUtf8());
|
||||
|
||||
// request is not successful
|
||||
assertThrows(IOException.class, () ->
|
||||
api.addContact(properties, mailboxContact));
|
||||
RecordedRequest request2 = server.takeRequest();
|
||||
assertEquals("/contacts", request2.getPath());
|
||||
assertToken(request2, token);
|
||||
|
||||
// contact already exists
|
||||
assertThrows(TolerableFailureException.class, () ->
|
||||
api.addContact(properties, mailboxContact));
|
||||
RecordedRequest request3 = server.takeRequest();
|
||||
assertEquals("/contacts", request3.getPath());
|
||||
assertToken(request3, token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddContactOnlyForOwner() {
|
||||
MailboxProperties properties =
|
||||
new MailboxProperties("", token, false);
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
api.addContact(properties, mailboxContact));
|
||||
}
|
||||
|
||||
private String getBaseUrl(MockWebServer server) {
|
||||
String baseUrl = server.url("").toString();
|
||||
return baseUrl.substring(0, baseUrl.length() - 1);
|
||||
|
||||
Reference in New Issue
Block a user