mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Address review comments for MailboxApi
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package org.briarproject.bramble.mailbox;
|
package org.briarproject.bramble.mailbox;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
@@ -25,19 +27,6 @@ interface MailboxApi {
|
|||||||
boolean checkStatus(MailboxProperties properties)
|
boolean checkStatus(MailboxProperties properties)
|
||||||
throws IOException, PermanentFailureException;
|
throws IOException, PermanentFailureException;
|
||||||
|
|
||||||
@Immutable
|
|
||||||
class MailboxProperties {
|
|
||||||
final String baseUrl;
|
|
||||||
final String token;
|
|
||||||
final boolean isOwner;
|
|
||||||
|
|
||||||
MailboxProperties(String baseUrl, String token, boolean isOwner) {
|
|
||||||
this.baseUrl = baseUrl;
|
|
||||||
this.token = token;
|
|
||||||
this.isOwner = isOwner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
class PermanentFailureException extends Exception {
|
class PermanentFailureException extends Exception {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.WeakSingletonProvider;
|
import org.briarproject.bramble.api.WeakSingletonProvider;
|
||||||
|
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -18,6 +19,7 @@ import okhttp3.ResponseBody;
|
|||||||
|
|
||||||
import static com.fasterxml.jackson.databind.MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES;
|
import static com.fasterxml.jackson.databind.MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES;
|
||||||
import static okhttp3.internal.Util.EMPTY_REQUEST;
|
import static okhttp3.internal.Util.EMPTY_REQUEST;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.fromHexString;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class MailboxApiImpl implements MailboxApi {
|
class MailboxApiImpl implements MailboxApi {
|
||||||
@@ -35,15 +37,16 @@ class MailboxApiImpl implements MailboxApi {
|
|||||||
@Override
|
@Override
|
||||||
public String setup(MailboxProperties properties)
|
public String setup(MailboxProperties properties)
|
||||||
throws IOException, PermanentFailureException {
|
throws IOException, PermanentFailureException {
|
||||||
if (!properties.isOwner) throw new IllegalArgumentException();
|
if (!properties.isOwner()) throw new IllegalArgumentException();
|
||||||
Request request = getRequestBuilder(properties.token)
|
Request request = getRequestBuilder(properties.getAuthToken())
|
||||||
.url(properties.baseUrl + "/setup")
|
.url(properties.getOnionAddress() + "/setup")
|
||||||
.put(EMPTY_REQUEST)
|
.put(EMPTY_REQUEST)
|
||||||
.build();
|
.build();
|
||||||
OkHttpClient client = httpClientProvider.get();
|
OkHttpClient client = httpClientProvider.get();
|
||||||
Response response = client.newCall(request).execute();
|
Response response = client.newCall(request).execute();
|
||||||
|
// TODO consider throwing a special exception for the 401 case
|
||||||
if (response.code() == 401) throw new PermanentFailureException();
|
if (response.code() == 401) throw new PermanentFailureException();
|
||||||
if (!response.isSuccessful()) throw new IOException();
|
if (!response.isSuccessful()) throw new PermanentFailureException();
|
||||||
ResponseBody body = response.body();
|
ResponseBody body = response.body();
|
||||||
if (body == null) throw new PermanentFailureException();
|
if (body == null) throw new PermanentFailureException();
|
||||||
try {
|
try {
|
||||||
@@ -53,7 +56,7 @@ class MailboxApiImpl implements MailboxApi {
|
|||||||
throw new PermanentFailureException();
|
throw new PermanentFailureException();
|
||||||
}
|
}
|
||||||
String ownerToken = tokenNode.textValue();
|
String ownerToken = tokenNode.textValue();
|
||||||
if (ownerToken == null) {
|
if (ownerToken == null || !isValidToken(ownerToken)) {
|
||||||
throw new PermanentFailureException();
|
throw new PermanentFailureException();
|
||||||
}
|
}
|
||||||
return ownerToken;
|
return ownerToken;
|
||||||
@@ -62,12 +65,23 @@ class MailboxApiImpl implements MailboxApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isValidToken(String token) {
|
||||||
|
if (token.length() != 64) return false;
|
||||||
|
try {
|
||||||
|
// try to convert to bytes
|
||||||
|
fromHexString(token);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkStatus(MailboxProperties properties)
|
public boolean checkStatus(MailboxProperties properties)
|
||||||
throws IOException, PermanentFailureException {
|
throws IOException, PermanentFailureException {
|
||||||
if (!properties.isOwner) throw new IllegalArgumentException();
|
if (!properties.isOwner()) throw new IllegalArgumentException();
|
||||||
Request request = getRequestBuilder(properties.token)
|
Request request = getRequestBuilder(properties.getAuthToken())
|
||||||
.url(properties.baseUrl + "/status")
|
.url(properties.getOnionAddress() + "/status")
|
||||||
.build();
|
.build();
|
||||||
OkHttpClient client = httpClientProvider.get();
|
OkHttpClient client = httpClientProvider.get();
|
||||||
Response response = client.newCall(request).execute();
|
Response response = client.newCall(request).execute();
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package org.briarproject.bramble.mailbox;
|
package org.briarproject.bramble.mailbox;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.WeakSingletonProvider;
|
import org.briarproject.bramble.api.WeakSingletonProvider;
|
||||||
import org.briarproject.bramble.mailbox.MailboxApi.MailboxProperties;
|
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||||
import org.briarproject.bramble.mailbox.MailboxApi.PermanentFailureException;
|
import org.briarproject.bramble.mailbox.MailboxApi.PermanentFailureException;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
@@ -17,7 +15,9 @@ import okhttp3.mockwebserver.MockWebServer;
|
|||||||
import okhttp3.mockwebserver.RecordedRequest;
|
import okhttp3.mockwebserver.RecordedRequest;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
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.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
@@ -40,14 +40,16 @@ public class MailboxApiTest extends BrambleTestCase {
|
|||||||
};
|
};
|
||||||
private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider);
|
private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider);
|
||||||
|
|
||||||
private final String token = getRandomString(64);
|
private final String token = toHexString(getRandomBytes(32));
|
||||||
private final String token2 = getRandomString(64);
|
private final String token2 = toHexString(getRandomBytes(32));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetup() throws Exception {
|
public void testSetup() throws Exception {
|
||||||
String validResponse = "{\"token\":\"" + token2 + "\"}";
|
String validResponse = "{\"token\":\"" + token2 + "\"}";
|
||||||
String invalidResponse = "{\"foo\":\"bar\"}";
|
String invalidResponse = "{\"foo\":\"bar\"}";
|
||||||
String invalidTokenResponse = "{\"token\":{\"foo\":\"bar\"}}";
|
String invalidTokenResponse = "{\"token\":{\"foo\":\"bar\"}}";
|
||||||
|
String invalidTokenResponse2 =
|
||||||
|
"{\"token\":\"" + getRandomString(64) + "\"}";
|
||||||
|
|
||||||
MockWebServer server = new MockWebServer();
|
MockWebServer server = new MockWebServer();
|
||||||
server.enqueue(new MockResponse().setBody(validResponse));
|
server.enqueue(new MockResponse().setBody(validResponse));
|
||||||
@@ -56,6 +58,7 @@ public class MailboxApiTest extends BrambleTestCase {
|
|||||||
server.enqueue(new MockResponse().setResponseCode(401));
|
server.enqueue(new MockResponse().setResponseCode(401));
|
||||||
server.enqueue(new MockResponse().setResponseCode(500));
|
server.enqueue(new MockResponse().setResponseCode(500));
|
||||||
server.enqueue(new MockResponse().setBody(invalidTokenResponse));
|
server.enqueue(new MockResponse().setBody(invalidTokenResponse));
|
||||||
|
server.enqueue(new MockResponse().setBody(invalidTokenResponse2));
|
||||||
server.start();
|
server.start();
|
||||||
String baseUrl = getBaseUrl(server);
|
String baseUrl = getBaseUrl(server);
|
||||||
MailboxProperties properties =
|
MailboxProperties properties =
|
||||||
@@ -63,49 +66,62 @@ public class MailboxApiTest extends BrambleTestCase {
|
|||||||
MailboxProperties properties2 =
|
MailboxProperties properties2 =
|
||||||
new MailboxProperties(baseUrl, token2, true);
|
new MailboxProperties(baseUrl, token2, true);
|
||||||
|
|
||||||
|
// valid response with valid token
|
||||||
assertEquals(token2, api.setup(properties));
|
assertEquals(token2, api.setup(properties));
|
||||||
|
|
||||||
assertThrows(PermanentFailureException.class,
|
|
||||||
() -> api.setup(properties));
|
|
||||||
assertThrows(PermanentFailureException.class,
|
|
||||||
() -> api.setup(properties));
|
|
||||||
assertThrows(PermanentFailureException.class,
|
|
||||||
() -> api.setup(properties2));
|
|
||||||
assertThrows(IOException.class,
|
|
||||||
() -> api.setup(properties));
|
|
||||||
assertThrows(PermanentFailureException.class,
|
|
||||||
() -> api.setup(properties)
|
|
||||||
);
|
|
||||||
|
|
||||||
RecordedRequest request1 = server.takeRequest();
|
RecordedRequest request1 = server.takeRequest();
|
||||||
assertEquals("/setup", request1.getPath());
|
assertEquals("/setup", request1.getPath());
|
||||||
assertEquals("PUT", request1.getMethod());
|
assertEquals("PUT", request1.getMethod());
|
||||||
assertToken(request1, token);
|
assertToken(request1, token);
|
||||||
|
|
||||||
|
// empty body
|
||||||
|
assertThrows(PermanentFailureException.class,
|
||||||
|
() -> api.setup(properties));
|
||||||
RecordedRequest request2 = server.takeRequest();
|
RecordedRequest request2 = server.takeRequest();
|
||||||
assertEquals("/setup", request2.getPath());
|
assertEquals("/setup", request2.getPath());
|
||||||
assertEquals("PUT", request2.getMethod());
|
assertEquals("PUT", request2.getMethod());
|
||||||
assertToken(request2, token);
|
assertToken(request2, token);
|
||||||
|
|
||||||
|
// invalid response
|
||||||
|
assertThrows(PermanentFailureException.class,
|
||||||
|
() -> api.setup(properties));
|
||||||
RecordedRequest request3 = server.takeRequest();
|
RecordedRequest request3 = server.takeRequest();
|
||||||
assertEquals("/setup", request3.getPath());
|
assertEquals("/setup", request3.getPath());
|
||||||
assertEquals("PUT", request3.getMethod());
|
assertEquals("PUT", request3.getMethod());
|
||||||
assertToken(request3, token);
|
assertToken(request3, token);
|
||||||
|
|
||||||
|
// 401 response
|
||||||
|
assertThrows(PermanentFailureException.class,
|
||||||
|
() -> api.setup(properties2));
|
||||||
RecordedRequest request4 = server.takeRequest();
|
RecordedRequest request4 = server.takeRequest();
|
||||||
assertEquals("/setup", request4.getPath());
|
assertEquals("/setup", request4.getPath());
|
||||||
assertEquals("PUT", request4.getMethod());
|
assertEquals("PUT", request4.getMethod());
|
||||||
assertToken(request4, token2);
|
assertToken(request4, token2);
|
||||||
|
|
||||||
|
// 500 response
|
||||||
|
assertThrows(PermanentFailureException.class,
|
||||||
|
() -> api.setup(properties));
|
||||||
RecordedRequest request5 = server.takeRequest();
|
RecordedRequest request5 = server.takeRequest();
|
||||||
assertEquals("/setup", request5.getPath());
|
assertEquals("/setup", request5.getPath());
|
||||||
assertEquals("PUT", request5.getMethod());
|
assertEquals("PUT", request5.getMethod());
|
||||||
assertToken(request5, token);
|
assertToken(request5, token);
|
||||||
|
|
||||||
|
// invalid json dict token response
|
||||||
|
assertThrows(PermanentFailureException.class,
|
||||||
|
() -> api.setup(properties)
|
||||||
|
);
|
||||||
RecordedRequest request6 = server.takeRequest();
|
RecordedRequest request6 = server.takeRequest();
|
||||||
assertEquals("/setup", request6.getPath());
|
assertEquals("/setup", request6.getPath());
|
||||||
assertEquals("PUT", request6.getMethod());
|
assertEquals("PUT", request6.getMethod());
|
||||||
assertToken(request6, token);
|
assertToken(request6, token);
|
||||||
|
|
||||||
|
// invalid non-hex string token response
|
||||||
|
assertThrows(PermanentFailureException.class,
|
||||||
|
() -> api.setup(properties)
|
||||||
|
);
|
||||||
|
RecordedRequest request7 = server.takeRequest();
|
||||||
|
assertEquals("/setup", request7.getPath());
|
||||||
|
assertEquals("PUT", request7.getMethod());
|
||||||
|
assertToken(request7, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -132,21 +148,18 @@ public class MailboxApiTest extends BrambleTestCase {
|
|||||||
new MailboxProperties(baseUrl, token2, true);
|
new MailboxProperties(baseUrl, token2, true);
|
||||||
|
|
||||||
assertTrue(api.checkStatus(properties));
|
assertTrue(api.checkStatus(properties));
|
||||||
|
|
||||||
assertThrows(PermanentFailureException.class, () ->
|
|
||||||
api.checkStatus(properties2)
|
|
||||||
);
|
|
||||||
|
|
||||||
assertFalse(api.checkStatus(properties));
|
|
||||||
|
|
||||||
RecordedRequest request1 = server.takeRequest();
|
RecordedRequest request1 = server.takeRequest();
|
||||||
assertEquals("/status", request1.getPath());
|
assertEquals("/status", request1.getPath());
|
||||||
assertToken(request1, token);
|
assertToken(request1, token);
|
||||||
|
|
||||||
|
assertThrows(PermanentFailureException.class, () ->
|
||||||
|
api.checkStatus(properties2)
|
||||||
|
);
|
||||||
RecordedRequest request2 = server.takeRequest();
|
RecordedRequest request2 = server.takeRequest();
|
||||||
assertEquals("/status", request2.getPath());
|
assertEquals("/status", request2.getPath());
|
||||||
assertToken(request2, token2);
|
assertToken(request2, token2);
|
||||||
|
|
||||||
|
assertFalse(api.checkStatus(properties));
|
||||||
RecordedRequest request3 = server.takeRequest();
|
RecordedRequest request3 = server.takeRequest();
|
||||||
assertEquals("/status", request3.getPath());
|
assertEquals("/status", request3.getPath());
|
||||||
assertToken(request3, token);
|
assertToken(request3, token);
|
||||||
|
|||||||
Reference in New Issue
Block a user