Add support for revealing contacts to the PrivateGroupManager

This also adds two integration tests and improves some small details
This commit is contained in:
Torsten Grote
2016-11-08 22:26:56 -02:00
parent b20c107010
commit ec8982438a
13 changed files with 402 additions and 156 deletions

View File

@@ -11,6 +11,7 @@ import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.KeyPair;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.event.Event;
@@ -20,6 +21,7 @@ import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.GroupMember;
import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageFactory;
import org.briarproject.api.privategroup.GroupMessageHeader;
@@ -59,6 +61,10 @@ import javax.inject.Inject;
import static org.briarproject.TestPluginsModule.MAX_LATENCY;
import static org.briarproject.TestUtils.getRandomBytes;
import static org.briarproject.api.identity.Author.Status.VERIFIED;
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_YOU;
import static org.briarproject.api.privategroup.Visibility.VISIBLE;
import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
@@ -69,13 +75,16 @@ import static org.junit.Assert.assertTrue;
public class PrivateGroupManagerTest extends BriarIntegrationTest {
private LifecycleManager lifecycleManager0, lifecycleManager1;
private SyncSessionFactory sync0, sync1;
private PrivateGroupManager groupManager0, groupManager1;
private ContactManager contactManager0, contactManager1;
private ContactId contactId0, contactId1;
private IdentityManager identityManager0, identityManager1;
private LocalAuthor author0, author1;
private LifecycleManager lifecycleManager0, lifecycleManager1,
lifecycleManager2;
private SyncSessionFactory sync0, sync1, sync2;
private PrivateGroupManager groupManager0, groupManager1, groupManager2;
private ContactManager contactManager0, contactManager1, contactManager2;
private ContactId contactId01, contactId02, contactId1, contactId2;
private IdentityManager identityManager0, identityManager1,
identityManager2;
private LocalAuthor author0, author1, author2;
private DatabaseComponent db0, db1, db2;
private PrivateGroup privateGroup0;
private GroupId groupId0;
@@ -101,13 +110,14 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
private final File testDir = TestUtils.getTestDirectory();
private final SecretKey master = TestUtils.getSecretKey();
private final int TIMEOUT = 15000;
private final String AUTHOR0 = "Author 0";
private final String AUTHOR1 = "Author 1";
private final String AUTHOR2 = "Author 2";
private static final Logger LOG =
Logger.getLogger(PrivateGroupManagerTest.class.getName());
private PrivateGroupManagerTestComponent t0, t1;
private PrivateGroupManagerTestComponent t0, t1, t2;
@Rule
public ExpectedException thrown = ExpectedException.none();
@@ -117,26 +127,36 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
PrivateGroupManagerTestComponent component =
DaggerPrivateGroupManagerTestComponent.builder().build();
component.inject(this);
injectEagerSingletons(component);
assertTrue(testDir.mkdirs());
File t0Dir = new File(testDir, AUTHOR1);
File t0Dir = new File(testDir, AUTHOR0);
t0 = DaggerPrivateGroupManagerTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
injectEagerSingletons(t0);
File t1Dir = new File(testDir, AUTHOR2);
File t1Dir = new File(testDir, AUTHOR1);
t1 = DaggerPrivateGroupManagerTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
injectEagerSingletons(t1);
File t2Dir = new File(testDir, AUTHOR2);
t2 = DaggerPrivateGroupManagerTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
injectEagerSingletons(t2);
identityManager0 = t0.getIdentityManager();
identityManager1 = t1.getIdentityManager();
identityManager2 = t2.getIdentityManager();
contactManager0 = t0.getContactManager();
contactManager1 = t1.getContactManager();
contactManager2 = t2.getContactManager();
db0 = t0.getDatabaseComponent();
db1 = t1.getDatabaseComponent();
db2 = t2.getDatabaseComponent();
groupManager0 = t0.getPrivateGroupManager();
groupManager1 = t1.getPrivateGroupManager();
groupManager2 = t2.getPrivateGroupManager();
sync0 = t0.getSyncSessionFactory();
sync1 = t1.getSyncSessionFactory();
sync2 = t2.getSyncSessionFactory();
// initialize waiters fresh for each test
validationWaiter = new Waiter();
@@ -328,12 +348,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
groupManager0.getPreviousMsgId(groupId0));
// make group visible to 1
Transaction txn0 = t0.getDatabaseComponent().startTransaction(false);
t0.getDatabaseComponent()
.setVisibleToContact(txn0, contactId1, privateGroup0.getId(),
true);
t0.getDatabaseComponent().commitTransaction(txn0);
t0.getDatabaseComponent().endTransaction(txn0);
Transaction txn0 = db0.startTransaction(false);
db0.setVisibleToContact(txn0, contactId1, privateGroup0.getId(), true);
db0.commitTransaction(txn0);
db0.endTransaction(txn0);
// author1 joins privateGroup0 with wrong timestamp
joinTime = clock.currentTimeMillis();
@@ -353,12 +371,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
groupManager1.getPreviousMsgId(groupId0));
// make group visible to 0
Transaction txn1 = t1.getDatabaseComponent().startTransaction(false);
t1.getDatabaseComponent()
.setVisibleToContact(txn1, contactId0, privateGroup0.getId(),
true);
t1.getDatabaseComponent().commitTransaction(txn1);
t1.getDatabaseComponent().endTransaction(txn1);
Transaction txn1 = db1.startTransaction(false);
db1.setVisibleToContact(txn1, contactId01, privateGroup0.getId(), true);
db1.commitTransaction(txn1);
db1.endTransaction(txn1);
// sync join messages
sync0To1();
@@ -399,12 +415,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
groupManager0.getPreviousMsgId(groupId0));
// make group visible to 1
Transaction txn0 = t0.getDatabaseComponent().startTransaction(false);
t0.getDatabaseComponent()
.setVisibleToContact(txn0, contactId1, privateGroup0.getId(),
true);
t0.getDatabaseComponent().commitTransaction(txn0);
t0.getDatabaseComponent().endTransaction(txn0);
Transaction txn0 = db0.startTransaction(false);
db0.setVisibleToContact(txn0, contactId1, privateGroup0.getId(), true);
db0.commitTransaction(txn0);
db0.endTransaction(txn0);
// author1 joins privateGroup0 with wrong signature in join message
joinTime = clock.currentTimeMillis();
@@ -424,12 +438,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
groupManager1.getPreviousMsgId(groupId0));
// make group visible to 0
Transaction txn1 = t1.getDatabaseComponent().startTransaction(false);
t1.getDatabaseComponent()
.setVisibleToContact(txn1, contactId0, privateGroup0.getId(),
true);
t1.getDatabaseComponent().commitTransaction(txn1);
t1.getDatabaseComponent().endTransaction(txn1);
Transaction txn1 = db1.startTransaction(false);
db1.setVisibleToContact(txn1, contactId01, privateGroup0.getId(), true);
db1.commitTransaction(txn1);
db1.endTransaction(txn1);
// sync join messages
sync0To1();
@@ -445,6 +457,119 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
assertEquals(1, groupManager0.getHeaders(groupId0).size());
}
@Test
public void testGetMembers() throws Exception {
defaultInit();
Collection<GroupMember> members0 = groupManager0.getMembers(groupId0);
assertEquals(2, members0.size());
for (GroupMember m : members0) {
if (m.getAuthor().equals(author0)) {
assertEquals(VISIBLE, m.getVisibility());
} else {
assertEquals(author1, m.getAuthor());
assertEquals(VISIBLE, m.getVisibility());
}
}
Collection<GroupMember> members1 = groupManager1.getMembers(groupId0);
assertEquals(2, members1.size());
for (GroupMember m : members0) {
if (m.getAuthor().equals(author1)) {
assertEquals(VISIBLE, m.getVisibility());
} else {
assertEquals(author0, m.getAuthor());
assertEquals(VISIBLE, m.getVisibility());
}
}
}
@Test
public void testRevealingRelationships() throws Exception {
defaultInit();
// make group visible to 2
Transaction txn0 = db0.startTransaction(false);
db0.setVisibleToContact(txn0, contactId2, privateGroup0.getId(), true);
db0.commitTransaction(txn0);
db0.endTransaction(txn0);
// author2 joins privateGroup0
long joinTime = clock.currentTimeMillis();
long inviteTime = joinTime - 1;
Group invitationGroup = contactGroupFactory
.createContactGroup(CLIENT_ID, author0.getId(),
author2.getId());
BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(),
privateGroup0.getId());
byte[] creatorSignature =
clientHelper.sign(toSign, author0.getPrivateKey());
GroupMessage joinMsg2 = groupMessageFactory
.createJoinMessage(privateGroup0.getId(), joinTime, author2,
inviteTime, creatorSignature);
Transaction txn2 = db2.startTransaction(false);
groupManager2.addPrivateGroup(txn2, privateGroup0, joinMsg2);
// make group visible to 0
db2.setVisibleToContact(txn2, contactId01, privateGroup0.getId(), true);
db2.commitTransaction(txn2);
db2.endTransaction(txn2);
// sync join messages
deliverMessage(sync2, contactId2, sync0, contactId02, "2 to 0");
deliveryWaiter.await(TIMEOUT, 1);
deliverMessage(sync0, contactId02, sync2, contactId2, "0 to 2");
deliveryWaiter.await(TIMEOUT, 2);
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
// check that everybody sees everybody else as joined
Collection<GroupMember> members0 = groupManager0.getMembers(groupId0);
assertEquals(3, members0.size());
Collection<GroupMember> members1 = groupManager1.getMembers(groupId0);
assertEquals(3, members1.size());
Collection<GroupMember> members2 = groupManager2.getMembers(groupId0);
assertEquals(3, members2.size());
// assert that contact relationship is not revealed initially
for (GroupMember m : members1) {
if (m.getAuthor().equals(author2)) {
assertEquals(INVISIBLE, m.getVisibility());
}
}
for (GroupMember m : members2) {
if (m.getAuthor().equals(author1)) {
assertEquals(INVISIBLE, m.getVisibility());
}
}
// reveal contact relationship
Transaction txn1 = db1.startTransaction(false);
groupManager1
.relationshipRevealed(txn1, groupId0, author2.getId(), false);
db1.commitTransaction(txn1);
db1.endTransaction(txn1);
txn2 = db2.startTransaction(false);
groupManager2
.relationshipRevealed(txn2, groupId0, author1.getId(), true);
db2.commitTransaction(txn2);
db2.endTransaction(txn2);
// assert that contact relationship is now revealed properly
members1 = groupManager1.getMembers(groupId0);
for (GroupMember m : members1) {
if (m.getAuthor().equals(author2)) {
assertEquals(REVEALED_BY_YOU, m.getVisibility());
}
}
members2 = groupManager2.getMembers(groupId0);
for (GroupMember m : members2) {
if (m.getAuthor().equals(author1)) {
assertEquals(REVEALED_BY_CONTACT, m.getVisibility());
}
}
}
@After
public void tearDown() throws Exception {
stopLifecycles();
@@ -483,7 +608,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
byte[] publicKey0 = keyPair0.getPublic().getEncoded();
byte[] privateKey0 = keyPair0.getPrivate().getEncoded();
author0 = authorFactory
.createLocalAuthor(AUTHOR1, publicKey0, privateKey0);
.createLocalAuthor(AUTHOR0, publicKey0, privateKey0);
identityManager0.registerLocalAuthor(author0);
privateGroup0 =
privateGroupFactory.createPrivateGroup("Testgroup", author0);
@@ -493,21 +618,34 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
byte[] publicKey1 = keyPair1.getPublic().getEncoded();
byte[] privateKey1 = keyPair1.getPrivate().getEncoded();
author1 = authorFactory
.createLocalAuthor(AUTHOR2, publicKey1, privateKey1);
.createLocalAuthor(AUTHOR1, publicKey1, privateKey1);
identityManager1.registerLocalAuthor(author1);
KeyPair keyPair2 = crypto.generateSignatureKeyPair();
byte[] publicKey2 = keyPair2.getPublic().getEncoded();
byte[] privateKey2 = keyPair2.getPrivate().getEncoded();
author2 = authorFactory
.createLocalAuthor(AUTHOR2, publicKey2, privateKey2);
identityManager2.registerLocalAuthor(author2);
}
private void addDefaultContacts() throws DbException {
// sharer adds invitee as contact
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true, true
);
// invitee adds sharer back
contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true,
true, true
);
// creator adds invitee as contact
contactId1 = contactManager0
.addContact(author1, author0.getId(), master,
clock.currentTimeMillis(), true, true, true);
// invitee adds creator back
contactId01 = contactManager1
.addContact(author0, author1.getId(), master,
clock.currentTimeMillis(), true, true, true);
// creator adds invitee as contact
contactId2 = contactManager0
.addContact(author2, author0.getId(), master,
clock.currentTimeMillis(), true, true, true);
// invitee adds creator back
contactId02 = contactManager2
.addContact(author0, author2.getId(), master,
clock.currentTimeMillis(), true, true, true);
}
private void listenToEvents() {
@@ -515,6 +653,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
t0.getEventBus().addListener(listener0);
Listener listener1 = new Listener();
t1.getEventBus().addListener(listener1);
Listener listener2 = new Listener();
t2.getEventBus().addListener(listener2);
}
private void addGroup() throws Exception {
@@ -527,12 +667,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
groupManager0.getPreviousMsgId(groupId0));
// make group visible to 1
Transaction txn0 = t0.getDatabaseComponent().startTransaction(false);
t0.getDatabaseComponent()
.setVisibleToContact(txn0, contactId1, privateGroup0.getId(),
true);
t0.getDatabaseComponent().commitTransaction(txn0);
t0.getDatabaseComponent().endTransaction(txn0);
Transaction txn0 = db0.startTransaction(false);
db0.setVisibleToContact(txn0, contactId1, privateGroup0.getId(), true);
db0.commitTransaction(txn0);
db0.endTransaction(txn0);
// author1 joins privateGroup0
joinTime = clock.currentTimeMillis();
@@ -547,17 +685,15 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
GroupMessage joinMsg1 = groupMessageFactory
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
inviteTime, creatorSignature);
groupManager1.addPrivateGroup(privateGroup0, joinMsg1);
assertEquals(joinMsg1.getMessage().getId(),
groupManager1.getPreviousMsgId(groupId0));
Transaction txn1 = db1.startTransaction(false);
groupManager1.addPrivateGroup(txn1, privateGroup0, joinMsg1);
// make group visible to 0
Transaction txn1 = t1.getDatabaseComponent().startTransaction(false);
t1.getDatabaseComponent()
.setVisibleToContact(txn1, contactId0, privateGroup0.getId(),
true);
t1.getDatabaseComponent().commitTransaction(txn1);
t1.getDatabaseComponent().endTransaction(txn1);
db1.setVisibleToContact(txn1, contactId01, privateGroup0.getId(), true);
db1.commitTransaction(txn1);
db1.endTransaction(txn1);
assertEquals(joinMsg1.getMessage().getId(),
groupManager1.getPreviousMsgId(groupId0));
// sync join messages
sync0To1();
@@ -567,11 +703,11 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
}
private void sync0To1() throws IOException, TimeoutException {
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
deliverMessage(sync0, contactId01, sync1, contactId1, "0 to 1");
}
private void sync1To0() throws IOException, TimeoutException {
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
deliverMessage(sync1, contactId1, sync0, contactId01, "1 to 0");
}
private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
@@ -600,18 +736,23 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
// Start the lifecycle manager and wait for it to finish
lifecycleManager0 = t0.getLifecycleManager();
lifecycleManager1 = t1.getLifecycleManager();
lifecycleManager0.startServices(AUTHOR1);
lifecycleManager1.startServices(AUTHOR2);
lifecycleManager2 = t2.getLifecycleManager();
lifecycleManager0.startServices(AUTHOR0);
lifecycleManager1.startServices(AUTHOR1);
lifecycleManager2.startServices(AUTHOR2);
lifecycleManager0.waitForStartup();
lifecycleManager1.waitForStartup();
lifecycleManager2.waitForStartup();
}
private void stopLifecycles() throws InterruptedException {
// Clean up
lifecycleManager0.stopServices();
lifecycleManager1.stopServices();
lifecycleManager2.stopServices();
lifecycleManager0.waitForShutdown();
lifecycleManager1.waitForShutdown();
lifecycleManager2.waitForShutdown();
}
private void injectEagerSingletons(