mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 05:39:53 +01:00
Merge branch '756-group-visibility' into 'master'
Add third group visibility state This branch adds a third group visibility state: each group is either invisible, visible, or shared with respect to each contact. Invisible means that the contact doesn't see any sign that we subscribe to the group. Visible means that the contact can send us messages in the group, but we won't send the contact messages in the group. Shared means that the contact can send us messages in the group and we'll send the contact any shared messages in the group. This is a preparatory step for #756. I'll put up another MR with the changes that close that ticket. See merge request !410
This commit is contained in:
@@ -66,6 +66,7 @@ import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
|
|||||||
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
|
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
|
||||||
import static org.briarproject.api.privategroup.Visibility.VISIBLE;
|
import static org.briarproject.api.privategroup.Visibility.VISIBLE;
|
||||||
import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
|
import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.PENDING;
|
import static org.briarproject.api.sync.ValidationManager.State.PENDING;
|
||||||
@@ -348,9 +349,9 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
assertEquals(joinMsg0.getMessage().getId(),
|
assertEquals(joinMsg0.getMessage().getId(),
|
||||||
groupManager0.getPreviousMsgId(groupId0));
|
groupManager0.getPreviousMsgId(groupId0));
|
||||||
|
|
||||||
// make group visible to 1
|
// share the group with 1
|
||||||
Transaction txn0 = db0.startTransaction(false);
|
Transaction txn0 = db0.startTransaction(false);
|
||||||
db0.setVisibleToContact(txn0, contactId1, privateGroup0.getId(), true);
|
db0.setGroupVisibility(txn0, contactId1, privateGroup0.getId(), SHARED);
|
||||||
db0.commitTransaction(txn0);
|
db0.commitTransaction(txn0);
|
||||||
db0.endTransaction(txn0);
|
db0.endTransaction(txn0);
|
||||||
|
|
||||||
@@ -371,9 +372,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
assertEquals(joinMsg1.getMessage().getId(),
|
assertEquals(joinMsg1.getMessage().getId(),
|
||||||
groupManager1.getPreviousMsgId(groupId0));
|
groupManager1.getPreviousMsgId(groupId0));
|
||||||
|
|
||||||
// make group visible to 0
|
// share the group with 0
|
||||||
Transaction txn1 = db1.startTransaction(false);
|
Transaction txn1 = db1.startTransaction(false);
|
||||||
db1.setVisibleToContact(txn1, contactId01, privateGroup0.getId(), true);
|
db1.setGroupVisibility(txn1, contactId01, privateGroup0.getId(),
|
||||||
|
SHARED);
|
||||||
db1.commitTransaction(txn1);
|
db1.commitTransaction(txn1);
|
||||||
db1.endTransaction(txn1);
|
db1.endTransaction(txn1);
|
||||||
|
|
||||||
@@ -415,9 +417,9 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
assertEquals(joinMsg0.getMessage().getId(),
|
assertEquals(joinMsg0.getMessage().getId(),
|
||||||
groupManager0.getPreviousMsgId(groupId0));
|
groupManager0.getPreviousMsgId(groupId0));
|
||||||
|
|
||||||
// make group visible to 1
|
// share the group with 1
|
||||||
Transaction txn0 = db0.startTransaction(false);
|
Transaction txn0 = db0.startTransaction(false);
|
||||||
db0.setVisibleToContact(txn0, contactId1, privateGroup0.getId(), true);
|
db0.setGroupVisibility(txn0, contactId1, privateGroup0.getId(), SHARED);
|
||||||
db0.commitTransaction(txn0);
|
db0.commitTransaction(txn0);
|
||||||
db0.endTransaction(txn0);
|
db0.endTransaction(txn0);
|
||||||
|
|
||||||
@@ -438,9 +440,9 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
assertEquals(joinMsg1.getMessage().getId(),
|
assertEquals(joinMsg1.getMessage().getId(),
|
||||||
groupManager1.getPreviousMsgId(groupId0));
|
groupManager1.getPreviousMsgId(groupId0));
|
||||||
|
|
||||||
// make group visible to 0
|
// share the group with 0
|
||||||
Transaction txn1 = db1.startTransaction(false);
|
Transaction txn1 = db1.startTransaction(false);
|
||||||
db1.setVisibleToContact(txn1, contactId01, privateGroup0.getId(), true);
|
db1.setGroupVisibility(txn1, contactId01, privateGroup0.getId(), SHARED);
|
||||||
db1.commitTransaction(txn1);
|
db1.commitTransaction(txn1);
|
||||||
db1.endTransaction(txn1);
|
db1.endTransaction(txn1);
|
||||||
|
|
||||||
@@ -518,9 +520,9 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
public void testRevealingRelationships() throws Exception {
|
public void testRevealingRelationships() throws Exception {
|
||||||
defaultInit();
|
defaultInit();
|
||||||
|
|
||||||
// make group visible to 2
|
// share the group with 2
|
||||||
Transaction txn0 = db0.startTransaction(false);
|
Transaction txn0 = db0.startTransaction(false);
|
||||||
db0.setVisibleToContact(txn0, contactId2, privateGroup0.getId(), true);
|
db0.setGroupVisibility(txn0, contactId2, privateGroup0.getId(), SHARED);
|
||||||
db0.commitTransaction(txn0);
|
db0.commitTransaction(txn0);
|
||||||
db0.endTransaction(txn0);
|
db0.endTransaction(txn0);
|
||||||
|
|
||||||
@@ -540,8 +542,9 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
Transaction txn2 = db2.startTransaction(false);
|
Transaction txn2 = db2.startTransaction(false);
|
||||||
groupManager2.addPrivateGroup(txn2, privateGroup0, joinMsg2, false);
|
groupManager2.addPrivateGroup(txn2, privateGroup0, joinMsg2, false);
|
||||||
|
|
||||||
// make group visible to 0
|
// share the group with 0
|
||||||
db2.setVisibleToContact(txn2, contactId01, privateGroup0.getId(), true);
|
db2.setGroupVisibility(txn2, contactId01, privateGroup0.getId(),
|
||||||
|
SHARED);
|
||||||
db2.commitTransaction(txn2);
|
db2.commitTransaction(txn2);
|
||||||
db2.endTransaction(txn2);
|
db2.endTransaction(txn2);
|
||||||
|
|
||||||
@@ -741,9 +744,9 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
assertEquals(joinMsg0.getMessage().getId(),
|
assertEquals(joinMsg0.getMessage().getId(),
|
||||||
groupManager0.getPreviousMsgId(groupId0));
|
groupManager0.getPreviousMsgId(groupId0));
|
||||||
|
|
||||||
// make group visible to 1
|
// share the group with 1
|
||||||
Transaction txn0 = db0.startTransaction(false);
|
Transaction txn0 = db0.startTransaction(false);
|
||||||
db0.setVisibleToContact(txn0, contactId1, privateGroup0.getId(), true);
|
db0.setGroupVisibility(txn0, contactId1, privateGroup0.getId(), SHARED);
|
||||||
db0.commitTransaction(txn0);
|
db0.commitTransaction(txn0);
|
||||||
db0.endTransaction(txn0);
|
db0.endTransaction(txn0);
|
||||||
|
|
||||||
@@ -762,9 +765,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
inviteTime, creatorSignature);
|
inviteTime, creatorSignature);
|
||||||
groupManager1.addPrivateGroup(privateGroup0, joinMsg1, false);
|
groupManager1.addPrivateGroup(privateGroup0, joinMsg1, false);
|
||||||
|
|
||||||
// make group visible to 0
|
// share the group with 0
|
||||||
Transaction txn1 = db1.startTransaction(false);
|
Transaction txn1 = db1.startTransaction(false);
|
||||||
db1.setVisibleToContact(txn1, contactId01, privateGroup0.getId(), true);
|
db1.setGroupVisibility(txn1, contactId01, privateGroup0.getId(),
|
||||||
|
SHARED);
|
||||||
db1.commitTransaction(txn1);
|
db1.commitTransaction(txn1);
|
||||||
db1.endTransaction(txn1);
|
db1.endTransaction(txn1);
|
||||||
assertEquals(joinMsg1.getMessage().getId(),
|
assertEquals(joinMsg1.getMessage().getId(),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.briarproject.api.settings.Settings;
|
|||||||
import org.briarproject.api.sync.Ack;
|
import org.briarproject.api.sync.Ack;
|
||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
|
import org.briarproject.api.sync.Group.Visibility;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.Message;
|
import org.briarproject.api.sync.Message;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
@@ -232,6 +233,15 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
Collection<Group> getGroups(Transaction txn, ClientId c) throws DbException;
|
Collection<Group> getGroups(Transaction txn, ClientId c) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given group's visibility to the given contact, or
|
||||||
|
* {@link Visibility INVISIBLE} if the group is not in the database.
|
||||||
|
* <p/>
|
||||||
|
* Read-only.
|
||||||
|
*/
|
||||||
|
Visibility getGroupVisibility(Transaction txn, ContactId c, GroupId g)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the local pseudonym with the given ID.
|
* Returns the local pseudonym with the given ID.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -388,14 +398,6 @@ public interface DatabaseComponent {
|
|||||||
void incrementStreamCounter(Transaction txn, ContactId c, TransportId t,
|
void incrementStreamCounter(Transaction txn, ContactId c, TransportId t,
|
||||||
long rotationPeriod) throws DbException;
|
long rotationPeriod) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the given group is visible to the given contact.
|
|
||||||
* <p/>
|
|
||||||
* Read-only.
|
|
||||||
*/
|
|
||||||
boolean isVisibleToContact(Transaction txn, ContactId c, GroupId g)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the given metadata with the existing metadata for the given
|
* Merges the given metadata with the existing metadata for the given
|
||||||
* group.
|
* group.
|
||||||
@@ -470,6 +472,12 @@ public interface DatabaseComponent {
|
|||||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the given group's visibility to the given contact.
|
||||||
|
*/
|
||||||
|
void setGroupVisibility(Transaction txn, ContactId c, GroupId g,
|
||||||
|
Visibility v) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given message as shared.
|
* Marks the given message as shared.
|
||||||
*/
|
*/
|
||||||
@@ -494,12 +502,6 @@ public interface DatabaseComponent {
|
|||||||
void setReorderingWindow(Transaction txn, ContactId c, TransportId t,
|
void setReorderingWindow(Transaction txn, ContactId c, TransportId t,
|
||||||
long rotationPeriod, long base, byte[] bitmap) throws DbException;
|
long rotationPeriod, long base, byte[] bitmap) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a group visible or invisible to a contact.
|
|
||||||
*/
|
|
||||||
void setVisibleToContact(Transaction txn, ContactId c, GroupId g,
|
|
||||||
boolean visible) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given transport keys, deleting any keys they have replaced.
|
* Stores the given transport keys, deleting any keys they have replaced.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ package org.briarproject.api.sync;
|
|||||||
|
|
||||||
public class Group {
|
public class Group {
|
||||||
|
|
||||||
|
public enum Visibility {
|
||||||
|
INVISIBLE, // The group is not visible
|
||||||
|
VISIBLE, // The group is visible but messages are not shared
|
||||||
|
SHARED // The group is visible and messages are shared
|
||||||
|
}
|
||||||
|
|
||||||
private final GroupId id;
|
private final GroupId id;
|
||||||
private final ClientId clientId;
|
private final ClientId clientId;
|
||||||
private final byte[] descriptor;
|
private final byte[] descriptor;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import org.briarproject.api.blogs.MessageType;
|
|||||||
import org.briarproject.api.clients.Client;
|
import org.briarproject.api.clients.Client;
|
||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
import org.briarproject.api.contact.Contact;
|
import org.briarproject.api.contact.Contact;
|
||||||
import org.briarproject.api.contact.ContactId;
|
|
||||||
import org.briarproject.api.contact.ContactManager;
|
import org.briarproject.api.contact.ContactManager;
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfEntry;
|
import org.briarproject.api.data.BdfEntry;
|
||||||
@@ -68,6 +67,7 @@ import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
|
|||||||
import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
|
import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
|
||||||
import static org.briarproject.api.contact.ContactManager.AddContactHook;
|
import static org.briarproject.api.contact.ContactManager.AddContactHook;
|
||||||
import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary;
|
import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -96,35 +96,24 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createLocalState(Transaction txn) throws DbException {
|
public void createLocalState(Transaction txn) throws DbException {
|
||||||
// Ensure that the local identity has its own personal blog
|
// Create our personal blog if necessary
|
||||||
LocalAuthor la = identityManager.getLocalAuthor(txn);
|
LocalAuthor a = identityManager.getLocalAuthor(txn);
|
||||||
Blog b = blogFactory.createBlog(la);
|
Blog b = blogFactory.createBlog(a);
|
||||||
Group g = b.getGroup();
|
db.addGroup(txn, b.getGroup());
|
||||||
if (!db.containsGroup(txn, g.getId())) {
|
// Ensure that we have the personal blogs of all contacts
|
||||||
db.addGroup(txn, g);
|
|
||||||
for (ContactId c : db.getContacts(txn, la.getId())) {
|
|
||||||
db.setVisibleToContact(txn, c, g.getId(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Ensure that we have the personal blogs of all pre-existing contacts
|
|
||||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||||
// get personal blog of the contact
|
// Add the personal blog of the contact and share it with the contact
|
||||||
Blog b = blogFactory.createBlog(c.getAuthor());
|
Blog b = blogFactory.createBlog(c.getAuthor());
|
||||||
Group g = b.getGroup();
|
db.addGroup(txn, b.getGroup());
|
||||||
if (!db.containsGroup(txn, g.getId())) {
|
db.setGroupVisibility(txn, c.getId(), b.getId(), SHARED);
|
||||||
// add the personal blog of the contact
|
// Share our personal blog with the contact
|
||||||
db.addGroup(txn, g);
|
LocalAuthor a = identityManager.getLocalAuthor(txn);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
Blog b2 = blogFactory.createBlog(a);
|
||||||
|
db.setGroupVisibility(txn, c.getId(), b2.getId(), SHARED);
|
||||||
// share our personal blog with the new contact
|
|
||||||
LocalAuthor a = db.getLocalAuthor(txn, c.getLocalAuthorId());
|
|
||||||
Blog b2 = blogFactory.createBlog(a);
|
|
||||||
db.setVisibleToContact(txn, c.getId(), b2.getId(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.briarproject.api.identity.LocalAuthor;
|
|||||||
import org.briarproject.api.settings.Settings;
|
import org.briarproject.api.settings.Settings;
|
||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
|
import org.briarproject.api.sync.Group.Visibility;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.Message;
|
import org.briarproject.api.sync.Message;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
@@ -72,6 +73,13 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void addGroup(T txn, Group g) throws DbException;
|
void addGroup(T txn, Group g) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the given group's visibility to the given contact to either
|
||||||
|
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||||
|
*/
|
||||||
|
void addGroupVisibility(T txn, ContactId c, GroupId g, boolean shared)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a local pseudonym.
|
* Stores a local pseudonym.
|
||||||
*/
|
*/
|
||||||
@@ -98,7 +106,7 @@ interface Database<T> {
|
|||||||
* Initialises the status of the given message with respect to the given
|
* Initialises the status of the given message with respect to the given
|
||||||
* contact.
|
* contact.
|
||||||
*
|
*
|
||||||
* @param ack whether the message needs to be acknowledged.
|
* @param ack whether the message needs to be acknowledged.
|
||||||
* @param seen whether the contact has seen the message.
|
* @param seen whether the contact has seen the message.
|
||||||
*/
|
*/
|
||||||
void addStatus(T txn, ContactId c, MessageId m, boolean ack, boolean seen)
|
void addStatus(T txn, ContactId c, MessageId m, boolean ack, boolean seen)
|
||||||
@@ -116,11 +124,6 @@ interface Database<T> {
|
|||||||
void addTransportKeys(T txn, ContactId c, TransportKeys k)
|
void addTransportKeys(T txn, ContactId c, TransportKeys k)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a group visible to the given contact.
|
|
||||||
*/
|
|
||||||
void addVisibility(T txn, ContactId c, GroupId g) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the database contains the given contact for the given
|
* Returns true if the database contains the given contact for the given
|
||||||
* local pseudonym.
|
* local pseudonym.
|
||||||
@@ -166,17 +169,9 @@ interface Database<T> {
|
|||||||
boolean containsTransport(T txn, TransportId t) throws DbException;
|
boolean containsTransport(T txn, TransportId t) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the database contains the given group and the group is
|
* Returns true if the database contains the given message, the message is
|
||||||
* visible to the given contact.
|
* shared, and the visibility of the message's group to the given contact
|
||||||
* <p/>
|
* is either {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||||
* Read-only.
|
|
||||||
*/
|
|
||||||
boolean containsVisibleGroup(T txn, ContactId c, GroupId g)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the database contains the given message and the message
|
|
||||||
* is visible to the given contact.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
@@ -267,6 +262,24 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Collection<Group> getGroups(T txn, ClientId c) throws DbException;
|
Collection<Group> getGroups(T txn, ClientId c) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given group's visibility to the given contact, or
|
||||||
|
* {@link Visibility INVISIBLE} if the group is not in the database.
|
||||||
|
* <p/>
|
||||||
|
* Read-only.
|
||||||
|
*/
|
||||||
|
Visibility getGroupVisibility(T txn, ContactId c, GroupId g)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the IDs of all contacts to which the given group's visibility is
|
||||||
|
* either {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||||
|
* <p/>
|
||||||
|
* Read-only.
|
||||||
|
*/
|
||||||
|
Collection<ContactId> getGroupVisibility(T txn, GroupId g)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the local pseudonym with the given ID.
|
* Returns the local pseudonym with the given ID.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -477,13 +490,6 @@ interface Database<T> {
|
|||||||
Map<ContactId, TransportKeys> getTransportKeys(T txn, TransportId t)
|
Map<ContactId, TransportKeys> getTransportKeys(T txn, TransportId t)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the IDs of all contacts to which the given group is visible.
|
|
||||||
* <p/>
|
|
||||||
* Read-only.
|
|
||||||
*/
|
|
||||||
Collection<ContactId> getVisibility(T txn, GroupId g) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the outgoing stream counter for the given contact and
|
* Increments the outgoing stream counter for the given contact and
|
||||||
* transport in the given rotation period.
|
* transport in the given rotation period.
|
||||||
@@ -550,6 +556,13 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void removeGroup(T txn, GroupId g) throws DbException;
|
void removeGroup(T txn, GroupId g) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the given group's visibility to the given contact to
|
||||||
|
* {@link Visibility INVISIBLE}.
|
||||||
|
*/
|
||||||
|
void removeGroupVisibility(T txn, ContactId c, GroupId g)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a local pseudonym (and all associated state) from the database.
|
* Removes a local pseudonym (and all associated state) from the database.
|
||||||
*/
|
*/
|
||||||
@@ -585,11 +598,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void removeTransport(T txn, TransportId t) throws DbException;
|
void removeTransport(T txn, TransportId t) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a group invisible to the given contact.
|
|
||||||
*/
|
|
||||||
void removeVisibility(T txn, ContactId c, GroupId g) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the transmission count and expiry time of the given message with
|
* Resets the transmission count and expiry time of the given message with
|
||||||
* respect to the given contact.
|
* respect to the given contact.
|
||||||
@@ -607,6 +615,13 @@ interface Database<T> {
|
|||||||
void setContactActive(T txn, ContactId c, boolean active)
|
void setContactActive(T txn, ContactId c, boolean active)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the given group's visibility to the given contact to either
|
||||||
|
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||||
|
*/
|
||||||
|
void setGroupVisibility(T txn, ContactId c, GroupId g, boolean shared)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given message as shared.
|
* Marks the given message as shared.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.briarproject.api.settings.Settings;
|
|||||||
import org.briarproject.api.sync.Ack;
|
import org.briarproject.api.sync.Ack;
|
||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
|
import org.briarproject.api.sync.Group.Visibility;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.Message;
|
import org.briarproject.api.sync.Message;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
@@ -66,6 +67,8 @@ import java.util.logging.Logger;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
||||||
@@ -97,6 +100,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
@Override
|
@Override
|
||||||
public boolean open() throws DbException {
|
public boolean open() throws DbException {
|
||||||
Runnable shutdownHook = new Runnable() {
|
Runnable shutdownHook = new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
@@ -223,7 +227,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
private void addMessage(T txn, Message m, State state, boolean shared,
|
private void addMessage(T txn, Message m, State state, boolean shared,
|
||||||
@Nullable ContactId sender) throws DbException {
|
@Nullable ContactId sender) throws DbException {
|
||||||
db.addMessage(txn, m, state, shared);
|
db.addMessage(txn, m, state, shared);
|
||||||
for (ContactId c : db.getVisibility(txn, m.getGroupId())) {
|
for (ContactId c : db.getGroupVisibility(txn, m.getGroupId())) {
|
||||||
boolean offered = db.removeOfferedMessage(txn, c, m.getId());
|
boolean offered = db.removeOfferedMessage(txn, c, m.getId());
|
||||||
boolean seen = offered || c.equals(sender);
|
boolean seen = offered || c.equals(sender);
|
||||||
db.addStatus(txn, c, m.getId(), seen, seen);
|
db.addStatus(txn, c, m.getId(), seen, seen);
|
||||||
@@ -441,6 +445,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
return db.getGroups(txn, c);
|
return db.getGroups(txn, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Visibility getGroupVisibility(Transaction transaction, ContactId c,
|
||||||
|
GroupId g) throws DbException {
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsContact(txn, c))
|
||||||
|
throw new NoSuchContactException();
|
||||||
|
return db.getGroupVisibility(txn, c, g);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalAuthor getLocalAuthor(Transaction transaction, AuthorId a)
|
public LocalAuthor getLocalAuthor(Transaction transaction, AuthorId a)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -602,17 +615,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
db.incrementStreamCounter(txn, c, t, rotationPeriod);
|
db.incrementStreamCounter(txn, c, t, rotationPeriod);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisibleToContact(Transaction transaction, ContactId c,
|
|
||||||
GroupId g) throws DbException {
|
|
||||||
T txn = unbox(transaction);
|
|
||||||
if (!db.containsContact(txn, c))
|
|
||||||
throw new NoSuchContactException();
|
|
||||||
if (!db.containsGroup(txn, g))
|
|
||||||
throw new NoSuchGroupException();
|
|
||||||
return db.containsVisibleGroup(txn, c, g);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeGroupMetadata(Transaction transaction, GroupId g,
|
public void mergeGroupMetadata(Transaction transaction, GroupId g,
|
||||||
Metadata meta) throws DbException {
|
Metadata meta) throws DbException {
|
||||||
@@ -672,7 +674,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsContact(txn, c))
|
if (!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
if (db.containsVisibleGroup(txn, c, m.getGroupId())) {
|
if (db.getGroupVisibility(txn, c, m.getGroupId()) != INVISIBLE) {
|
||||||
if (db.containsMessage(txn, m.getId())) {
|
if (db.containsMessage(txn, m.getId())) {
|
||||||
db.raiseSeenFlag(txn, c, m.getId());
|
db.raiseSeenFlag(txn, c, m.getId());
|
||||||
db.raiseAckFlag(txn, c, m.getId());
|
db.raiseAckFlag(txn, c, m.getId());
|
||||||
@@ -745,7 +747,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
GroupId id = g.getId();
|
GroupId id = g.getId();
|
||||||
if (!db.containsGroup(txn, id))
|
if (!db.containsGroup(txn, id))
|
||||||
throw new NoSuchGroupException();
|
throw new NoSuchGroupException();
|
||||||
Collection<ContactId> affected = db.getVisibility(txn, id);
|
Collection<ContactId> affected = db.getGroupVisibility(txn, id);
|
||||||
db.removeGroup(txn, id);
|
db.removeGroup(txn, id);
|
||||||
transaction.attach(new GroupRemovedEvent(g));
|
transaction.attach(new GroupRemovedEvent(g));
|
||||||
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
|
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
|
||||||
@@ -794,6 +796,34 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
transaction.attach(new ContactStatusChangedEvent(c, active));
|
transaction.attach(new ContactStatusChangedEvent(c, active));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGroupVisibility(Transaction transaction, ContactId c,
|
||||||
|
GroupId g, Visibility v) throws DbException {
|
||||||
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsContact(txn, c))
|
||||||
|
throw new NoSuchContactException();
|
||||||
|
if (!db.containsGroup(txn, g))
|
||||||
|
throw new NoSuchGroupException();
|
||||||
|
Visibility old = db.getGroupVisibility(txn, c, g);
|
||||||
|
if (old == v) return;
|
||||||
|
if (old == INVISIBLE) {
|
||||||
|
db.addGroupVisibility(txn, c, g, v == SHARED);
|
||||||
|
for (MessageId m : db.getMessageIds(txn, g)) {
|
||||||
|
boolean seen = db.removeOfferedMessage(txn, c, m);
|
||||||
|
db.addStatus(txn, c, m, seen, seen);
|
||||||
|
}
|
||||||
|
} else if (v == INVISIBLE) {
|
||||||
|
db.removeGroupVisibility(txn, c, g);
|
||||||
|
for (MessageId m : db.getMessageIds(txn, g))
|
||||||
|
db.removeStatus(txn, c, m);
|
||||||
|
} else {
|
||||||
|
db.setGroupVisibility(txn, c, g, v == SHARED);
|
||||||
|
}
|
||||||
|
List<ContactId> affected = Collections.singletonList(c);
|
||||||
|
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMessageShared(Transaction transaction, MessageId m)
|
public void setMessageShared(Transaction transaction, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -845,33 +875,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
db.setReorderingWindow(txn, c, t, rotationPeriod, base, bitmap);
|
db.setReorderingWindow(txn, c, t, rotationPeriod, base, bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVisibleToContact(Transaction transaction, ContactId c,
|
|
||||||
GroupId g, boolean visible) throws DbException {
|
|
||||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
|
||||||
T txn = unbox(transaction);
|
|
||||||
if (!db.containsContact(txn, c))
|
|
||||||
throw new NoSuchContactException();
|
|
||||||
if (!db.containsGroup(txn, g))
|
|
||||||
throw new NoSuchGroupException();
|
|
||||||
boolean wasVisible = db.containsVisibleGroup(txn, c, g);
|
|
||||||
if (visible && !wasVisible) {
|
|
||||||
db.addVisibility(txn, c, g);
|
|
||||||
for (MessageId m : db.getMessageIds(txn, g)) {
|
|
||||||
boolean seen = db.removeOfferedMessage(txn, c, m);
|
|
||||||
db.addStatus(txn, c, m, seen, seen);
|
|
||||||
}
|
|
||||||
} else if (!visible && wasVisible) {
|
|
||||||
db.removeVisibility(txn, c, g);
|
|
||||||
for (MessageId m : db.getMessageIds(txn, g))
|
|
||||||
db.removeStatus(txn, c, m);
|
|
||||||
}
|
|
||||||
if (visible != wasVisible) {
|
|
||||||
List<ContactId> affected = Collections.singletonList(c);
|
|
||||||
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTransportKeys(Transaction transaction,
|
public void updateTransportKeys(Transaction transaction,
|
||||||
Map<ContactId, TransportKeys> keys) throws DbException {
|
Map<ContactId, TransportKeys> keys) throws DbException {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -73,6 +73,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT
|
|||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
|
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -116,7 +117,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
if (db.containsGroup(txn, g.getId())) return;
|
if (db.containsGroup(txn, g.getId())) return;
|
||||||
// Store the group and share it with the contact
|
// Store the group and share it with the contact
|
||||||
db.addGroup(txn, g);
|
db.addGroup(txn, g);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||||
// Attach the contact ID to the group
|
// Attach the contact ID to the group
|
||||||
BdfDictionary gm = new BdfDictionary();
|
BdfDictionary gm = new BdfDictionary();
|
||||||
gm.put(CONTACT, c.getId().getInt());
|
gm.put(CONTACT, c.getId().getInt());
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
|
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -64,7 +65,7 @@ class MessagingManagerImpl extends ConversationClientImpl
|
|||||||
if (db.containsGroup(txn, g.getId())) return;
|
if (db.containsGroup(txn, g.getId())) return;
|
||||||
// Store the group and share it with the contact
|
// Store the group and share it with the contact
|
||||||
db.addGroup(txn, g);
|
db.addGroup(txn, g);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||||
// Attach the contact ID to the group
|
// Attach the contact ID to the group
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary d = new BdfDictionary();
|
||||||
d.put("contactId", c.getId().getInt());
|
d.put("contactId", c.getId().getInt());
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.briarproject.api.privategroup.PrivateGroup;
|
|||||||
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
||||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
|
import org.briarproject.api.sync.Group.Visibility;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.Message;
|
import org.briarproject.api.sync.Message;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
@@ -90,11 +91,10 @@ abstract class AbstractProtocolEngine<S extends Session>
|
|||||||
return dependency.equals(expected);
|
return dependency.equals(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncPrivateGroupWithContact(Transaction txn, S session, boolean sync)
|
void setPrivateGroupVisibility(Transaction txn, S session, Visibility v)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
ContactId contactId = getContactId(txn, session.getContactGroupId());
|
ContactId contactId = getContactId(txn, session.getContactGroupId());
|
||||||
db.setVisibleToContact(txn, contactId, session.getPrivateGroupId(),
|
db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), v);
|
||||||
sync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message sendInviteMessage(Transaction txn, S session,
|
Message sendInviteMessage(Transaction txn, S session,
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import org.briarproject.api.system.Clock;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.privategroup.invitation.CreatorState.DISSOLVED;
|
import static org.briarproject.privategroup.invitation.CreatorState.DISSOLVED;
|
||||||
import static org.briarproject.privategroup.invitation.CreatorState.ERROR;
|
import static org.briarproject.privategroup.invitation.CreatorState.ERROR;
|
||||||
import static org.briarproject.privategroup.invitation.CreatorState.INVITED;
|
import static org.briarproject.privategroup.invitation.CreatorState.INVITED;
|
||||||
@@ -158,8 +160,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
|||||||
private CreatorSession onLocalLeave(Transaction txn, CreatorSession s)
|
private CreatorSession onLocalLeave(Transaction txn, CreatorSession s)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
try {
|
try {
|
||||||
// Stop syncing the private group with the contact
|
// Make the private group invisible to the contact
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
@@ -183,8 +185,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
|||||||
// Track the message
|
// Track the message
|
||||||
messageTracker.trackMessage(txn, m.getContactGroupId(),
|
messageTracker.trackMessage(txn, m.getContactGroupId(),
|
||||||
m.getTimestamp(), false);
|
m.getTimestamp(), false);
|
||||||
// Start syncing the private group with the contact
|
// Share the private group with the contact
|
||||||
syncPrivateGroupWithContact(txn, s, true);
|
setPrivateGroupVisibility(txn, s, SHARED);
|
||||||
// Broadcast an event
|
// Broadcast an event
|
||||||
ContactId contactId = getContactId(txn, m.getContactGroupId());
|
ContactId contactId = getContactId(txn, m.getContactGroupId());
|
||||||
txn.attach(new GroupInvitationResponseReceivedEvent(contactId,
|
txn.attach(new GroupInvitationResponseReceivedEvent(contactId,
|
||||||
@@ -224,8 +226,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
|||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (!isValidDependency(s, m.getPreviousMessageId()))
|
if (!isValidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
// Stop syncing the private group with the contact
|
// Make the private group invisible to the contact
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
// Move to the INVITEE_LEFT state
|
// Move to the INVITEE_LEFT state
|
||||||
return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(),
|
return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(),
|
||||||
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
|
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
|
||||||
@@ -236,9 +238,9 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
|||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
// If the session has already been aborted, do nothing
|
// If the session has already been aborted, do nothing
|
||||||
if (s.getState() == ERROR) return s;
|
if (s.getState() == ERROR) return s;
|
||||||
// If we subscribe, stop syncing the private group with the contact
|
// If we subscribe, make the private group invisible to the contact
|
||||||
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
|
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
// Send an ABORT message
|
// Send an ABORT message
|
||||||
Message sent = sendAbortMessage(txn, s);
|
Message sent = sendAbortMessage(txn, s);
|
||||||
// Move to the ERROR state
|
// Move to the ERROR state
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import java.util.Map.Entry;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.privategroup.invitation.CreatorState.START;
|
import static org.briarproject.privategroup.invitation.CreatorState.START;
|
||||||
import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
|
import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
|
||||||
import static org.briarproject.privategroup.invitation.MessageType.ABORT;
|
import static org.briarproject.privategroup.invitation.MessageType.ABORT;
|
||||||
@@ -110,7 +111,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
|||||||
if (db.containsGroup(txn, g.getId())) return;
|
if (db.containsGroup(txn, g.getId())) return;
|
||||||
// Store the group and share it with the contact
|
// Store the group and share it with the contact
|
||||||
db.addGroup(txn, g);
|
db.addGroup(txn, g);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||||
// Attach the contact ID to the group
|
// Attach the contact ID to the group
|
||||||
BdfDictionary meta = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
|
meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import org.briarproject.api.system.Clock;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.privategroup.invitation.InviteeState.DISSOLVED;
|
import static org.briarproject.privategroup.invitation.InviteeState.DISSOLVED;
|
||||||
import static org.briarproject.privategroup.invitation.InviteeState.ERROR;
|
import static org.briarproject.privategroup.invitation.InviteeState.ERROR;
|
||||||
import static org.briarproject.privategroup.invitation.InviteeState.INVITED;
|
import static org.briarproject.privategroup.invitation.InviteeState.INVITED;
|
||||||
@@ -157,8 +159,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
|||||||
try {
|
try {
|
||||||
// Subscribe to the private group
|
// Subscribe to the private group
|
||||||
subscribeToPrivateGroup(txn, inviteId);
|
subscribeToPrivateGroup(txn, inviteId);
|
||||||
// Start syncing the private group with the contact
|
// Share the private group with the contact
|
||||||
syncPrivateGroupWithContact(txn, s, true);
|
setPrivateGroupVisibility(txn, s, SHARED);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
@@ -228,8 +230,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
|||||||
if (!isValidDependency(s, m.getPreviousMessageId()))
|
if (!isValidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
try {
|
try {
|
||||||
// Stop syncing the private group with the contact
|
// Make the private group invisible to the contact
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
@@ -247,9 +249,9 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
|||||||
if (s.getState() == ERROR) return s;
|
if (s.getState() == ERROR) return s;
|
||||||
// Mark any invite messages in the session unavailable to answer
|
// Mark any invite messages in the session unavailable to answer
|
||||||
markInvitesUnavailableToAnswer(txn, s);
|
markInvitesUnavailableToAnswer(txn, s);
|
||||||
// Stop syncing the private group with the contact, if we subscribe
|
// If we subscribe, make the private group invisible to the contact
|
||||||
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
|
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
// Send an ABORT message
|
// Send an ABORT message
|
||||||
Message sent = sendAbortMessage(txn, s);
|
Message sent = sendAbortMessage(txn, s);
|
||||||
// Move to the ERROR state
|
// Move to the ERROR state
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import org.briarproject.api.system.Clock;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.privategroup.invitation.PeerState.AWAIT_MEMBER;
|
import static org.briarproject.privategroup.invitation.PeerState.AWAIT_MEMBER;
|
||||||
import static org.briarproject.privategroup.invitation.PeerState.BOTH_JOINED;
|
import static org.briarproject.privategroup.invitation.PeerState.BOTH_JOINED;
|
||||||
import static org.briarproject.privategroup.invitation.PeerState.ERROR;
|
import static org.briarproject.privategroup.invitation.PeerState.ERROR;
|
||||||
@@ -178,8 +180,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
// Send a JOIN message
|
// Send a JOIN message
|
||||||
Message sent = sendJoinMessage(txn, s, false);
|
Message sent = sendJoinMessage(txn, s, false);
|
||||||
try {
|
try {
|
||||||
// Start syncing the private group with the contact
|
// Share the private group with the contact
|
||||||
syncPrivateGroupWithContact(txn, s, true);
|
setPrivateGroupVisibility(txn, s, SHARED);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
@@ -195,8 +197,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
// Send a LEAVE message
|
// Send a LEAVE message
|
||||||
Message sent = sendLeaveMessage(txn, s, false);
|
Message sent = sendLeaveMessage(txn, s, false);
|
||||||
try {
|
try {
|
||||||
// Stop syncing the private group with the contact
|
// Make the private group invisible to the contact
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
@@ -228,8 +230,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
// Send a JOIN message
|
// Send a JOIN message
|
||||||
Message sent = sendJoinMessage(txn, s, false);
|
Message sent = sendJoinMessage(txn, s, false);
|
||||||
try {
|
try {
|
||||||
// Start syncing the private group with the contact
|
// Share the private group with the contact
|
||||||
syncPrivateGroupWithContact(txn, s, true);
|
setPrivateGroupVisibility(txn, s, SHARED);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
@@ -263,8 +265,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
// Send a JOIN message
|
// Send a JOIN message
|
||||||
Message sent = sendJoinMessage(txn, s, false);
|
Message sent = sendJoinMessage(txn, s, false);
|
||||||
// Start syncing the private group with the contact
|
// Share the private group with the contact
|
||||||
syncPrivateGroupWithContact(txn, s, true);
|
setPrivateGroupVisibility(txn, s, SHARED);
|
||||||
// Mark the relationship visible to the group, revealed by contact
|
// Mark the relationship visible to the group, revealed by contact
|
||||||
relationshipRevealed(txn, s, true);
|
relationshipRevealed(txn, s, true);
|
||||||
// Move to the BOTH_JOINED state
|
// Move to the BOTH_JOINED state
|
||||||
@@ -277,8 +279,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (!isValidDependency(s, m.getPreviousMessageId()))
|
if (!isValidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
// Start syncing the private group with the contact
|
// Share the private group with the contact
|
||||||
syncPrivateGroupWithContact(txn, s, true);
|
setPrivateGroupVisibility(txn, s, SHARED);
|
||||||
// Mark the relationship visible to the group, revealed by us
|
// Mark the relationship visible to the group, revealed by us
|
||||||
relationshipRevealed(txn, s, false);
|
relationshipRevealed(txn, s, false);
|
||||||
// Move to the BOTH_JOINED state
|
// Move to the BOTH_JOINED state
|
||||||
@@ -314,8 +316,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (!isValidDependency(s, m.getPreviousMessageId()))
|
if (!isValidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
// Stop syncing the private group with the contact
|
// Make the private group invisible to the contact
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
// Move to the LOCAL_JOINED state
|
// Move to the LOCAL_JOINED state
|
||||||
return new PeerSession(s.getContactGroupId(), s.getPrivateGroupId(),
|
return new PeerSession(s.getContactGroupId(), s.getPrivateGroupId(),
|
||||||
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
|
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
|
||||||
@@ -326,9 +328,9 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
|||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
// If the session has already been aborted, do nothing
|
// If the session has already been aborted, do nothing
|
||||||
if (s.getState() == ERROR) return s;
|
if (s.getState() == ERROR) return s;
|
||||||
// Stop syncing the private group with the contact, if we subscribe
|
// If we subscribe, make the private group invisible to the contact
|
||||||
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
|
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
|
||||||
syncPrivateGroupWithContact(txn, s, false);
|
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||||
// Send an ABORT message
|
// Send an ABORT message
|
||||||
Message sent = sendAbortMessage(txn, s);
|
Message sent = sendAbortMessage(txn, s);
|
||||||
// Move to the ERROR state
|
// Move to the ERROR state
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
|
|
||||||
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||||
Client, AddContactHook, RemoveContactHook {
|
Client, AddContactHook, RemoveContactHook {
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
if (db.containsGroup(txn, g.getId())) return;
|
if (db.containsGroup(txn, g.getId())) return;
|
||||||
// Store the group and share it with the contact
|
// Store the group and share it with the contact
|
||||||
db.addGroup(txn, g);
|
db.addGroup(txn, g);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||||
// Copy the latest local properties into the group
|
// Copy the latest local properties into the group
|
||||||
Map<TransportId, TransportProperties> local = getLocalProperties(txn);
|
Map<TransportId, TransportProperties> local = getLocalProperties(txn);
|
||||||
for (Entry<TransportId, TransportProperties> e : local.entrySet()) {
|
for (Entry<TransportId, TransportProperties> e : local.entrySet()) {
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ import static org.briarproject.api.sharing.SharingConstants.TO_BE_SHARED_BY_US;
|
|||||||
import static org.briarproject.api.sharing.SharingConstants.TYPE;
|
import static org.briarproject.api.sharing.SharingConstants.TYPE;
|
||||||
import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
|
import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
|
||||||
import static org.briarproject.api.sharing.SharingMessage.Invitation;
|
import static org.briarproject.api.sharing.SharingMessage.Invitation;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
|
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
|
||||||
import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
|
import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
|
||||||
|
|
||||||
@@ -159,7 +161,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
|
|||||||
if (db.containsGroup(txn, g.getId())) return;
|
if (db.containsGroup(txn, g.getId())) return;
|
||||||
// Store the group and share it with the contact
|
// Store the group and share it with the contact
|
||||||
db.addGroup(txn, g);
|
db.addGroup(txn, g);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||||
// Attach the contact ID to the group
|
// Attach the contact ID to the group
|
||||||
BdfDictionary meta = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
meta.put(CONTACT_ID, c.getId().getInt());
|
meta.put(CONTACT_ID, c.getId().getInt());
|
||||||
@@ -908,20 +910,20 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
|
|||||||
// TODO we might want to call the add() method of the respective
|
// TODO we might want to call the add() method of the respective
|
||||||
// manager here, because blogs add a description for example
|
// manager here, because blogs add a description for example
|
||||||
db.addGroup(txn, f.getGroup());
|
db.addGroup(txn, f.getGroup());
|
||||||
db.setVisibleToContact(txn, contactId, f.getId(), true);
|
db.setGroupVisibility(txn, contactId, f.getId(), SHARED);
|
||||||
} else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {
|
} else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {
|
||||||
addToList(txn, groupId, TO_BE_SHARED_BY_US, f);
|
addToList(txn, groupId, TO_BE_SHARED_BY_US, f);
|
||||||
} else if (task == TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US) {
|
} else if (task == TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US) {
|
||||||
removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
|
removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
|
||||||
} else if (task == TASK_SHARE_SHAREABLE) {
|
} else if (task == TASK_SHARE_SHAREABLE) {
|
||||||
db.setVisibleToContact(txn, contactId, f.getId(), true);
|
db.setGroupVisibility(txn, contactId, f.getId(), SHARED);
|
||||||
removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
|
removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
|
||||||
addToList(txn, groupId, SHARED_BY_US, f);
|
addToList(txn, groupId, SHARED_BY_US, f);
|
||||||
} else if (task == TASK_UNSHARE_SHAREABLE_SHARED_BY_US) {
|
} else if (task == TASK_UNSHARE_SHAREABLE_SHARED_BY_US) {
|
||||||
db.setVisibleToContact(txn, contactId, f.getId(), false);
|
db.setGroupVisibility(txn, contactId, f.getId(), INVISIBLE);
|
||||||
removeFromList(txn, groupId, SHARED_BY_US, f);
|
removeFromList(txn, groupId, SHARED_BY_US, f);
|
||||||
} else if (task == TASK_UNSHARE_SHAREABLE_SHARED_WITH_US) {
|
} else if (task == TASK_UNSHARE_SHAREABLE_SHARED_WITH_US) {
|
||||||
db.setVisibleToContact(txn, contactId, f.getId(), false);
|
db.setGroupVisibility(txn, contactId, f.getId(), INVISIBLE);
|
||||||
removeFromList(txn, groupId, SHARED_WITH_US, f);
|
removeFromList(txn, groupId, SHARED_WITH_US, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import static org.briarproject.api.blogs.BlogConstants.KEY_TYPE;
|
|||||||
import static org.briarproject.api.blogs.MessageType.POST;
|
import static org.briarproject.api.blogs.MessageType.POST;
|
||||||
import static org.briarproject.api.identity.Author.Status.VERIFIED;
|
import static org.briarproject.api.identity.Author.Status.VERIFIED;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID;
|
import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -102,25 +103,18 @@ public class BlogManagerImplTest extends BriarTestCase {
|
|||||||
will(returnValue(blog1.getAuthor()));
|
will(returnValue(blog1.getAuthor()));
|
||||||
oneOf(blogFactory).createBlog(blog1.getAuthor());
|
oneOf(blogFactory).createBlog(blog1.getAuthor());
|
||||||
will(returnValue(blog1));
|
will(returnValue(blog1));
|
||||||
oneOf(db).containsGroup(txn, blog1.getId());
|
|
||||||
will(returnValue(false));
|
|
||||||
oneOf(db).addGroup(txn, blog1.getGroup());
|
oneOf(db).addGroup(txn, blog1.getGroup());
|
||||||
oneOf(db).getContacts(txn, blog1.getAuthor().getId());
|
|
||||||
will(returnValue(contactIds));
|
|
||||||
oneOf(db).setVisibleToContact(txn, contactId, blog1.getId(), true);
|
|
||||||
oneOf(db).getContacts(txn);
|
oneOf(db).getContacts(txn);
|
||||||
will(returnValue(contacts));
|
will(returnValue(contacts));
|
||||||
oneOf(blogFactory).createBlog(blog2.getAuthor());
|
oneOf(blogFactory).createBlog(blog2.getAuthor());
|
||||||
will(returnValue(blog2));
|
will(returnValue(blog2));
|
||||||
oneOf(db).containsGroup(txn, blog2.getId());
|
|
||||||
will(returnValue(false));
|
|
||||||
oneOf(db).addGroup(txn, blog2.getGroup());
|
oneOf(db).addGroup(txn, blog2.getGroup());
|
||||||
oneOf(db).setVisibleToContact(txn, contactId, blog2.getId(), true);
|
oneOf(db).setGroupVisibility(txn, contactId, blog2.getId(), SHARED);
|
||||||
oneOf(db).getLocalAuthor(txn, blog1.getAuthor().getId());
|
oneOf(identityManager).getLocalAuthor(txn);
|
||||||
will(returnValue(blog1.getAuthor()));
|
will(returnValue(blog1.getAuthor()));
|
||||||
oneOf(blogFactory).createBlog(blog1.getAuthor());
|
oneOf(blogFactory).createBlog(blog1.getAuthor());
|
||||||
will(returnValue(blog1));
|
will(returnValue(blog1));
|
||||||
oneOf(db).setVisibleToContact(txn, contactId, blog1.getId(), true);
|
oneOf(db).setGroupVisibility(txn, contactId, blog1.getId(), SHARED);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
blogManager.createLocalState(txn);
|
blogManager.createLocalState(txn);
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ import java.util.Collections;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
|
import static org.briarproject.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
|
||||||
@@ -170,7 +173,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
// removeGroup()
|
// removeGroup()
|
||||||
oneOf(database).containsGroup(txn, groupId);
|
oneOf(database).containsGroup(txn, groupId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).getVisibility(txn, groupId);
|
oneOf(database).getGroupVisibility(txn, groupId);
|
||||||
will(returnValue(Collections.emptyList()));
|
will(returnValue(Collections.emptyList()));
|
||||||
oneOf(database).removeGroup(txn, groupId);
|
oneOf(database).removeGroup(txn, groupId);
|
||||||
oneOf(eventBus).broadcast(with(any(GroupRemovedEvent.class)));
|
oneOf(eventBus).broadcast(with(any(GroupRemovedEvent.class)));
|
||||||
@@ -267,7 +270,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).addMessage(txn, message, DELIVERED, true);
|
oneOf(database).addMessage(txn, message, DELIVERED, true);
|
||||||
oneOf(database).mergeMessageMetadata(txn, messageId, metadata);
|
oneOf(database).mergeMessageMetadata(txn, messageId, metadata);
|
||||||
oneOf(database).getVisibility(txn, groupId);
|
oneOf(database).getGroupVisibility(txn, groupId);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
@@ -403,7 +406,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
transaction = db.startTransaction(false);
|
transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.isVisibleToContact(transaction, contactId, groupId);
|
db.getGroupVisibility(transaction, contactId, groupId);
|
||||||
fail();
|
fail();
|
||||||
} catch (NoSuchContactException expected) {
|
} catch (NoSuchContactException expected) {
|
||||||
// Expected
|
// Expected
|
||||||
@@ -487,7 +490,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
transaction = db.startTransaction(false);
|
transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.setVisibleToContact(transaction, contactId, groupId, true);
|
db.setGroupVisibility(transaction, contactId, groupId, SHARED);
|
||||||
fail();
|
fail();
|
||||||
} catch (NoSuchContactException expected) {
|
} catch (NoSuchContactException expected) {
|
||||||
// Expected
|
// Expected
|
||||||
@@ -560,14 +563,13 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
final EventBus eventBus = context.mock(EventBus.class);
|
final EventBus eventBus = context.mock(EventBus.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the group is in the DB (which it's not)
|
// Check whether the group is in the DB (which it's not)
|
||||||
exactly(9).of(database).startTransaction();
|
exactly(8).of(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
exactly(9).of(database).containsGroup(txn, groupId);
|
exactly(8).of(database).containsGroup(txn, groupId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
exactly(9).of(database).abortTransaction(txn);
|
exactly(8).of(database).abortTransaction(txn);
|
||||||
// This is needed for getMessageStatus(), isVisibleToContact(), and
|
// This is needed for getMessageStatus() and setGroupVisibility()
|
||||||
// setVisibleToContact() to proceed
|
exactly(2).of(database).containsContact(txn, contactId);
|
||||||
exactly(3).of(database).containsContact(txn, contactId);
|
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
@@ -623,16 +625,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction = db.startTransaction(false);
|
|
||||||
try {
|
|
||||||
db.isVisibleToContact(transaction, contactId, groupId);
|
|
||||||
fail();
|
|
||||||
} catch (NoSuchGroupException expected) {
|
|
||||||
// Expected
|
|
||||||
} finally {
|
|
||||||
db.endTransaction(transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction = db.startTransaction(false);
|
transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.mergeGroupMetadata(transaction, groupId, metadata);
|
db.mergeGroupMetadata(transaction, groupId, metadata);
|
||||||
@@ -655,7 +647,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
transaction = db.startTransaction(false);
|
transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.setVisibleToContact(transaction, contactId, groupId, true);
|
db.setGroupVisibility(transaction, contactId, groupId, SHARED);
|
||||||
fail();
|
fail();
|
||||||
} catch (NoSuchGroupException expected) {
|
} catch (NoSuchGroupException expected) {
|
||||||
// Expected
|
// Expected
|
||||||
@@ -924,6 +916,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
Ack a = db.generateAck(transaction, contactId, 123);
|
Ack a = db.generateAck(transaction, contactId, 123);
|
||||||
|
assertNotNull(a);
|
||||||
assertEquals(messagesToAck, a.getMessageIds());
|
assertEquals(messagesToAck, a.getMessageIds());
|
||||||
db.commitTransaction(transaction);
|
db.commitTransaction(transaction);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1005,6 +998,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
Offer o = db.generateOffer(transaction, contactId, 123, maxLatency);
|
Offer o = db.generateOffer(transaction, contactId, 123, maxLatency);
|
||||||
|
assertNotNull(o);
|
||||||
assertEquals(ids, o.getMessageIds());
|
assertEquals(ids, o.getMessageIds());
|
||||||
db.commitTransaction(transaction);
|
db.commitTransaction(transaction);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1039,6 +1033,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
Request r = db.generateRequest(transaction, contactId, 123);
|
Request r = db.generateRequest(transaction, contactId, 123);
|
||||||
|
assertNotNull(r);
|
||||||
assertEquals(ids, r.getMessageIds());
|
assertEquals(ids, r.getMessageIds());
|
||||||
db.commitTransaction(transaction);
|
db.commitTransaction(transaction);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1139,12 +1134,12 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
// First time
|
// First time
|
||||||
oneOf(database).containsContact(txn, contactId);
|
oneOf(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsVisibleGroup(txn, contactId, groupId);
|
oneOf(database).getGroupVisibility(txn, contactId, groupId);
|
||||||
will(returnValue(true));
|
will(returnValue(VISIBLE));
|
||||||
oneOf(database).containsMessage(txn, messageId);
|
oneOf(database).containsMessage(txn, messageId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).addMessage(txn, message, UNKNOWN, false);
|
oneOf(database).addMessage(txn, message, UNKNOWN, false);
|
||||||
oneOf(database).getVisibility(txn, groupId);
|
oneOf(database).getGroupVisibility(txn, groupId);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
@@ -1152,8 +1147,8 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
// Second time
|
// Second time
|
||||||
oneOf(database).containsContact(txn, contactId);
|
oneOf(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsVisibleGroup(txn, contactId, groupId);
|
oneOf(database).getGroupVisibility(txn, contactId, groupId);
|
||||||
will(returnValue(true));
|
will(returnValue(VISIBLE));
|
||||||
oneOf(database).containsMessage(txn, messageId);
|
oneOf(database).containsMessage(txn, messageId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).raiseSeenFlag(txn, contactId, messageId);
|
oneOf(database).raiseSeenFlag(txn, contactId, messageId);
|
||||||
@@ -1195,8 +1190,8 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsMessage(txn, messageId);
|
oneOf(database).containsMessage(txn, messageId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsVisibleGroup(txn, contactId, groupId);
|
oneOf(database).getGroupVisibility(txn, contactId, groupId);
|
||||||
will(returnValue(true));
|
will(returnValue(VISIBLE));
|
||||||
// The message wasn't stored but it must still be acked
|
// The message wasn't stored but it must still be acked
|
||||||
oneOf(database).raiseSeenFlag(txn, contactId, messageId);
|
oneOf(database).raiseSeenFlag(txn, contactId, messageId);
|
||||||
oneOf(database).raiseAckFlag(txn, contactId, messageId);
|
oneOf(database).raiseAckFlag(txn, contactId, messageId);
|
||||||
@@ -1230,8 +1225,8 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsContact(txn, contactId);
|
oneOf(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsVisibleGroup(txn, contactId, groupId);
|
oneOf(database).getGroupVisibility(txn, contactId, groupId);
|
||||||
will(returnValue(false));
|
will(returnValue(INVISIBLE));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
@@ -1350,9 +1345,9 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsGroup(txn, groupId);
|
oneOf(database).containsGroup(txn, groupId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsVisibleGroup(txn, contactId, groupId);
|
oneOf(database).getGroupVisibility(txn, contactId, groupId);
|
||||||
will(returnValue(false)); // Not yet visible
|
will(returnValue(INVISIBLE)); // Not yet visible
|
||||||
oneOf(database).addVisibility(txn, contactId, groupId);
|
oneOf(database).addGroupVisibility(txn, contactId, groupId, false);
|
||||||
oneOf(database).getMessageIds(txn, groupId);
|
oneOf(database).getMessageIds(txn, groupId);
|
||||||
will(returnValue(Collections.singletonList(messageId)));
|
will(returnValue(Collections.singletonList(messageId)));
|
||||||
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
||||||
@@ -1367,7 +1362,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.setVisibleToContact(transaction, contactId, groupId, true);
|
db.setGroupVisibility(transaction, contactId, groupId, VISIBLE);
|
||||||
db.commitTransaction(transaction);
|
db.commitTransaction(transaction);
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
@@ -1391,8 +1386,8 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsGroup(txn, groupId);
|
oneOf(database).containsGroup(txn, groupId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).containsVisibleGroup(txn, contactId, groupId);
|
oneOf(database).getGroupVisibility(txn, contactId, groupId);
|
||||||
will(returnValue(true)); // Already visible
|
will(returnValue(VISIBLE)); // Already visible
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
@@ -1400,7 +1395,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.setVisibleToContact(transaction, contactId, groupId, true);
|
db.setGroupVisibility(transaction, contactId, groupId, VISIBLE);
|
||||||
db.commitTransaction(transaction);
|
db.commitTransaction(transaction);
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
@@ -1666,7 +1661,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
|||||||
oneOf(database).containsMessage(txn, messageId);
|
oneOf(database).containsMessage(txn, messageId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).addMessage(txn, message, DELIVERED, true);
|
oneOf(database).addMessage(txn, message, DELIVERED, true);
|
||||||
oneOf(database).getVisibility(txn, groupId);
|
oneOf(database).getGroupVisibility(txn, groupId);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
oneOf(database).mergeMessageMetadata(txn, messageId, metadata);
|
oneOf(database).mergeMessageMetadata(txn, messageId, metadata);
|
||||||
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
oneOf(database).removeOfferedMessage(txn, contactId, messageId);
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.briarproject.api.db.Metadata.REMOVE;
|
import static org.briarproject.api.db.Metadata.REMOVE;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
|
import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
|
||||||
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
|
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
||||||
@@ -171,12 +174,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a group and a message
|
// Add a contact, a shared group and a shared message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
db.addMessage(txn, message, DELIVERED, true);
|
db.addMessage(txn, message, DELIVERED, true);
|
||||||
|
|
||||||
// The message has no status yet, so it should not be sendable
|
// The message has no status yet, so it should not be sendable
|
||||||
@@ -209,12 +212,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a group and an unvalidated message
|
// Add a contact, a shared group and a shared but unvalidated message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
db.addMessage(txn, message, UNKNOWN, true);
|
db.addMessage(txn, message, UNKNOWN, true);
|
||||||
db.addStatus(txn, contactId, messageId, false, false);
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
@@ -251,16 +254,68 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSendableMessagesMustBeShared() throws Exception {
|
public void testSendableMessagesMustHaveSharedGroup() throws Exception {
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a group and an unshared message
|
// Add a contact, an invisible group and a shared message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addMessage(txn, message, DELIVERED, true);
|
||||||
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
|
// The group is invisible, so the message should not be sendable
|
||||||
|
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
|
||||||
|
ONE_MEGABYTE);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
|
||||||
|
// Making the group visible should not make the message sendable
|
||||||
|
db.addGroupVisibility(txn, contactId, groupId, false);
|
||||||
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
|
||||||
|
// Sharing the group should make the message sendable
|
||||||
|
db.setGroupVisibility(txn, contactId, groupId, true);
|
||||||
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||||
|
assertEquals(Collections.singletonList(messageId), ids);
|
||||||
|
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||||
|
assertEquals(Collections.singletonList(messageId), ids);
|
||||||
|
|
||||||
|
// Unsharing the group should make the message unsendable
|
||||||
|
db.setGroupVisibility(txn, contactId, groupId, false);
|
||||||
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
|
||||||
|
// Making the group invisible should make the message unsendable
|
||||||
|
db.removeGroupVisibility(txn, contactId, groupId);
|
||||||
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||||
|
assertTrue(ids.isEmpty());
|
||||||
|
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendableMessagesMustBeShared() throws Exception {
|
||||||
|
Database<Connection> db = open(false);
|
||||||
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
|
// Add a contact, a shared group and an unshared message
|
||||||
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
|
true, true));
|
||||||
|
db.addGroup(txn, group);
|
||||||
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
db.addMessage(txn, message, DELIVERED, false);
|
db.addMessage(txn, message, DELIVERED, false);
|
||||||
db.addStatus(txn, contactId, messageId, false, false);
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
@@ -287,12 +342,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a group and a message
|
// Add a contact, a shared group and a shared message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
db.addMessage(txn, message, DELIVERED, true);
|
db.addMessage(txn, message, DELIVERED, true);
|
||||||
db.addStatus(txn, contactId, messageId, false, false);
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
@@ -314,12 +369,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and a group
|
// Add a contact and a visible group
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, false);
|
||||||
|
|
||||||
// Add some messages to ack
|
// Add some messages to ack
|
||||||
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
@@ -351,12 +406,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a group and a message
|
// Add a contact, a shared group and a shared message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
db.addMessage(txn, message, DELIVERED, true);
|
db.addMessage(txn, message, DELIVERED, true);
|
||||||
db.addStatus(txn, contactId, messageId, false, false);
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
@@ -515,12 +570,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact and a group
|
// Add a contact and a shared group
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
|
|
||||||
// The message is not in the database
|
// The message is not in the database
|
||||||
assertFalse(db.containsVisibleMessage(txn, contactId, messageId));
|
assertFalse(db.containsVisibleMessage(txn, contactId, messageId));
|
||||||
@@ -569,7 +624,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVisibility() throws Exception {
|
public void testGroupVisibility() throws Exception {
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
@@ -580,52 +635,33 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
|
|
||||||
// The group should not be visible to the contact
|
// The group should not be visible to the contact
|
||||||
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
assertEquals(INVISIBLE, db.getGroupVisibility(txn, contactId, groupId));
|
||||||
|
assertEquals(Collections.emptyList(),
|
||||||
|
db.getGroupVisibility(txn, groupId));
|
||||||
|
|
||||||
// Make the group visible to the contact
|
// Make the group visible to the contact
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, false);
|
||||||
|
assertEquals(VISIBLE, db.getGroupVisibility(txn, contactId, groupId));
|
||||||
assertEquals(Collections.singletonList(contactId),
|
assertEquals(Collections.singletonList(contactId),
|
||||||
db.getVisibility(txn, groupId));
|
db.getGroupVisibility(txn, groupId));
|
||||||
|
|
||||||
|
// Share the group with the contact
|
||||||
|
db.setGroupVisibility(txn, contactId, groupId, true);
|
||||||
|
assertEquals(SHARED, db.getGroupVisibility(txn, contactId, groupId));
|
||||||
|
assertEquals(Collections.singletonList(contactId),
|
||||||
|
db.getGroupVisibility(txn, groupId));
|
||||||
|
|
||||||
|
// Unshare the group with the contact
|
||||||
|
db.setGroupVisibility(txn, contactId, groupId, false);
|
||||||
|
assertEquals(VISIBLE, db.getGroupVisibility(txn, contactId, groupId));
|
||||||
|
assertEquals(Collections.singletonList(contactId),
|
||||||
|
db.getGroupVisibility(txn, groupId));
|
||||||
|
|
||||||
// Make the group invisible again
|
// Make the group invisible again
|
||||||
db.removeVisibility(txn, contactId, groupId);
|
db.removeGroupVisibility(txn, contactId, groupId);
|
||||||
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
assertEquals(INVISIBLE, db.getGroupVisibility(txn, contactId, groupId));
|
||||||
|
assertEquals(Collections.emptyList(),
|
||||||
db.commitTransaction(txn);
|
db.getGroupVisibility(txn, groupId));
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMultipleGroupChanges() throws Exception {
|
|
||||||
// Create some groups
|
|
||||||
List<Group> groups = new ArrayList<>();
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
GroupId id = new GroupId(TestUtils.getRandomId());
|
|
||||||
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
|
|
||||||
byte[] descriptor = new byte[0];
|
|
||||||
groups.add(new Group(id, clientId, descriptor));
|
|
||||||
}
|
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Add a contact and the groups
|
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
|
||||||
true, true));
|
|
||||||
for (Group g : groups) db.addGroup(txn, g);
|
|
||||||
|
|
||||||
// Make the groups visible to the contact
|
|
||||||
Collections.shuffle(groups);
|
|
||||||
for (Group g : groups) db.addVisibility(txn, contactId, g.getId());
|
|
||||||
|
|
||||||
// Make some of the groups invisible to the contact and remove them all
|
|
||||||
Collections.shuffle(groups);
|
|
||||||
for (Group g : groups) {
|
|
||||||
if (Math.random() < 0.5)
|
|
||||||
db.removeVisibility(txn, contactId, g.getId());
|
|
||||||
db.removeGroup(txn, g.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
db.close();
|
db.close();
|
||||||
@@ -1144,15 +1180,15 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
metadata1.put("foo", new byte[]{'b', 'a', 'r'});
|
metadata1.put("foo", new byte[]{'b', 'a', 'r'});
|
||||||
db.mergeMessageMetadata(txn, messageId1, metadata1);
|
db.mergeMessageMetadata(txn, messageId1, metadata1);
|
||||||
|
|
||||||
for (int i = 1; i <= 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
Metadata query;
|
Metadata query;
|
||||||
if (i == 1) {
|
if (i == 0) {
|
||||||
// Query the metadata with an empty query
|
// Query the metadata with an empty query
|
||||||
query = new Metadata();
|
query = new Metadata();
|
||||||
} else {
|
} else {
|
||||||
// Query for foo
|
// Query for foo
|
||||||
query = new Metadata();
|
query = new Metadata();
|
||||||
query.put("foo", metadata.get("foo"));
|
query.put("foo", new byte[]{'b', 'a', 'r'});
|
||||||
}
|
}
|
||||||
|
|
||||||
db.setMessageState(txn, messageId, DELIVERED);
|
db.setMessageState(txn, messageId, DELIVERED);
|
||||||
@@ -1160,32 +1196,39 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Map<MessageId, Metadata> all =
|
Map<MessageId, Metadata> all =
|
||||||
db.getMessageMetadata(txn, groupId, query);
|
db.getMessageMetadata(txn, groupId, query);
|
||||||
assertEquals(2, all.size());
|
assertEquals(2, all.size());
|
||||||
assertEquals(2, all.get(messageId).size());
|
assertMetadataEquals(metadata, all.get(messageId));
|
||||||
assertEquals(1, all.get(messageId1).size());
|
assertMetadataEquals(metadata1, all.get(messageId1));
|
||||||
|
|
||||||
// No metadata for unknown messages
|
// No metadata for unknown messages
|
||||||
db.setMessageState(txn, messageId, UNKNOWN);
|
db.setMessageState(txn, messageId, UNKNOWN);
|
||||||
db.setMessageState(txn, messageId1, UNKNOWN);
|
|
||||||
all = db.getMessageMetadata(txn, groupId, query);
|
all = db.getMessageMetadata(txn, groupId, query);
|
||||||
assertTrue(all.isEmpty());
|
assertEquals(1, all.size());
|
||||||
|
assertMetadataEquals(metadata1, all.get(messageId1));
|
||||||
|
|
||||||
// No metadata for invalid messages
|
// No metadata for invalid messages
|
||||||
db.setMessageState(txn, messageId, INVALID);
|
db.setMessageState(txn, messageId, INVALID);
|
||||||
db.setMessageState(txn, messageId1, INVALID);
|
|
||||||
all = db.getMessageMetadata(txn, groupId, query);
|
all = db.getMessageMetadata(txn, groupId, query);
|
||||||
assertTrue(all.isEmpty());
|
assertEquals(1, all.size());
|
||||||
|
assertMetadataEquals(metadata1, all.get(messageId1));
|
||||||
|
|
||||||
// No metadata for pending messages
|
// No metadata for pending messages
|
||||||
db.setMessageState(txn, messageId, PENDING);
|
db.setMessageState(txn, messageId, PENDING);
|
||||||
db.setMessageState(txn, messageId1, PENDING);
|
|
||||||
all = db.getMessageMetadata(txn, groupId, query);
|
all = db.getMessageMetadata(txn, groupId, query);
|
||||||
assertTrue(all.isEmpty());
|
assertEquals(1, all.size());
|
||||||
|
assertMetadataEquals(metadata1, all.get(messageId1));
|
||||||
}
|
}
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertMetadataEquals(Metadata m1, Metadata m2) {
|
||||||
|
assertEquals(m1.keySet(), m2.keySet());
|
||||||
|
for (Entry<String, byte[]> e : m1.entrySet()) {
|
||||||
|
assertArrayEquals(e.getValue(), m2.get(e.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMessageDependencies() throws Exception {
|
public void testMessageDependencies() throws Exception {
|
||||||
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
@@ -1398,16 +1441,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact, a shared group and a shared message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
|
|
||||||
// Add a group and make it visible to the contact
|
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
|
|
||||||
// Add a message to the group
|
|
||||||
db.addMessage(txn, message, DELIVERED, true);
|
db.addMessage(txn, message, DELIVERED, true);
|
||||||
db.addStatus(txn, contactId, messageId, false, false);
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
@@ -1471,33 +1510,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGroupsVisibleToContacts() throws Exception {
|
public void testDifferentLocalAuthorsCanHaveTheSameContact()
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Add a contact and a group
|
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
|
||||||
true, true));
|
|
||||||
db.addGroup(txn, group);
|
|
||||||
|
|
||||||
// The group should not be visible to the contact
|
|
||||||
assertFalse(db.containsVisibleGroup(txn, contactId, groupId));
|
|
||||||
|
|
||||||
// Make the group visible to the contact
|
|
||||||
db.addVisibility(txn, contactId, groupId);
|
|
||||||
assertTrue(db.containsVisibleGroup(txn, contactId, groupId));
|
|
||||||
|
|
||||||
// Make the group invisible to the contact
|
|
||||||
db.removeVisibility(txn, contactId, groupId);
|
|
||||||
assertFalse(db.containsVisibleGroup(txn, contactId, groupId));
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDifferentLocalPseudonymsCanHaveTheSameContact()
|
|
||||||
throws Exception {
|
throws Exception {
|
||||||
AuthorId localAuthorId1 = new AuthorId(TestUtils.getRandomId());
|
AuthorId localAuthorId1 = new AuthorId(TestUtils.getRandomId());
|
||||||
LocalAuthor localAuthor1 = new LocalAuthor(localAuthorId1, "Carol",
|
LocalAuthor localAuthor1 = new LocalAuthor(localAuthorId1, "Carol",
|
||||||
@@ -1506,11 +1519,11 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add two local pseudonyms
|
// Add two local authors
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
db.addLocalAuthor(txn, localAuthor1);
|
db.addLocalAuthor(txn, localAuthor1);
|
||||||
|
|
||||||
// Add the same contact for each local pseudonym
|
// Add the same contact for each local author
|
||||||
ContactId contactId =
|
ContactId contactId =
|
||||||
db.addContact(txn, author, localAuthorId, true, true);
|
db.addContact(txn, author, localAuthorId, true, true);
|
||||||
ContactId contactId1 =
|
ContactId contactId1 =
|
||||||
@@ -1531,12 +1544,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a group and a message
|
// Add a contact, a shared group and a shared message
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, localAuthor);
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
assertEquals(contactId, db.addContact(txn, author, localAuthorId,
|
||||||
true, true));
|
true, true));
|
||||||
db.addGroup(txn, group);
|
db.addGroup(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addGroupVisibility(txn, contactId, groupId, true);
|
||||||
db.addMessage(txn, message, DELIVERED, true);
|
db.addMessage(txn, message, DELIVERED, true);
|
||||||
db.addStatus(txn, contactId, messageId, false, false);
|
db.addStatus(txn, contactId, messageId, false, false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user