From be309057cd02b0417e794e8d58bdf47473ac5ecf Mon Sep 17 00:00:00 2001 From: akwizgran Date: Mon, 16 Apr 2018 14:53:48 +0100 Subject: [PATCH] Use client versioning for blogs and forums. --- .../briar/sharing/BlogProtocolEngineImpl.java | 23 ++-- .../briar/sharing/BlogSharingManagerImpl.java | 18 +++- .../sharing/ForumProtocolEngineImpl.java | 23 ++-- .../sharing/ForumSharingManagerImpl.java | 19 +++- .../briar/sharing/ProtocolEngineImpl.java | 19 +++- .../briar/sharing/SessionEncoderImpl.java | 2 + .../briar/sharing/SessionParser.java | 2 + .../briar/sharing/SessionParserImpl.java | 6 ++ .../briar/sharing/SharingConstants.java | 1 + .../briar/sharing/SharingManagerImpl.java | 101 +++++++++++++++--- .../briar/sharing/SharingModule.java | 27 +++++ .../org/briarproject/briar/sharing/State.java | 21 +++- .../sharing/BlogSharingManagerImplTest.java | 21 ++-- .../briar/test/BriarIntegrationTest.java | 3 + 14 files changed, 239 insertions(+), 47 deletions(-) diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java index 3083387b6..3ab61521d 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.blog.Blog; @@ -22,6 +23,9 @@ import org.briarproject.briar.api.sharing.InvitationRequest; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID; +import static org.briarproject.briar.api.blog.BlogManager.CLIENT_VERSION; + @Immutable @NotNullByDefault class BlogProtocolEngineImpl extends ProtocolEngineImpl { @@ -31,13 +35,14 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { invitationFactory; @Inject - BlogProtocolEngineImpl(DatabaseComponent db, - ClientHelper clientHelper, MessageEncoder messageEncoder, - MessageParser messageParser, MessageTracker messageTracker, - Clock clock, BlogManager blogManager, + BlogProtocolEngineImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, + MessageEncoder messageEncoder, MessageParser messageParser, + MessageTracker messageTracker, Clock clock, BlogManager blogManager, InvitationFactory invitationFactory) { - super(db, clientHelper, messageEncoder, messageParser, messageTracker, - clock); + super(db, clientHelper, clientVersioningManager, messageEncoder, + messageParser, messageTracker, clock, CLIENT_ID, + CLIENT_VERSION); this.blogManager = blogManager; this.invitationFactory = invitationFactory; } @@ -46,8 +51,8 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { Event getInvitationRequestReceivedEvent(InviteMessage m, ContactId contactId, boolean available, boolean canBeOpened) { InvitationRequest request = invitationFactory - .createInvitationRequest(false, false, true, false, m, - contactId, available, canBeOpened); + .createInvitationRequest(false, false, true, false, m, + contactId, available, canBeOpened); return new BlogInvitationRequestReceivedEvent(m.getShareable(), contactId, request); } @@ -74,7 +79,7 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { @Override protected ClientId getShareableClientId() { - return BlogManager.CLIENT_ID; + return CLIENT_ID; } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java index 7a92f1c5f..41554bcf4 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java @@ -12,6 +12,7 @@ import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.BlogInvitationResponse; import org.briarproject.briar.api.blog.BlogManager; @@ -32,6 +33,7 @@ class BlogSharingManagerImpl extends SharingManagerImpl @Inject BlogSharingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageParser messageParser, SessionEncoder sessionEncoder, SessionParser sessionParser, MessageTracker messageTracker, @@ -39,9 +41,9 @@ class BlogSharingManagerImpl extends SharingManagerImpl ProtocolEngine engine, InvitationFactory invitationFactory, IdentityManager identityManager, BlogManager blogManager) { - super(db, clientHelper, metadataParser, messageParser, sessionEncoder, - sessionParser, messageTracker, contactGroupFactory, engine, - invitationFactory); + super(db, clientHelper, clientVersioningManager, metadataParser, + messageParser, sessionEncoder, sessionParser, messageTracker, + contactGroupFactory, engine, invitationFactory); this.identityManager = identityManager; this.blogManager = blogManager; } @@ -56,6 +58,16 @@ class BlogSharingManagerImpl extends SharingManagerImpl return CLIENT_VERSION; } + @Override + protected ClientId getShareableClientId() { + return BlogManager.CLIENT_ID; + } + + @Override + protected int getShareableClientVersion() { + return BlogManager.CLIENT_VERSION; + } + @Override public void addingContact(Transaction txn, Contact c) throws DbException { // Create a group to share with the contact diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java index 9fb695e50..90ad6888d 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.client.MessageTracker; @@ -22,6 +23,9 @@ import org.briarproject.briar.api.sharing.InvitationRequest; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID; +import static org.briarproject.briar.api.forum.ForumManager.CLIENT_VERSION; + @Immutable @NotNullByDefault class ForumProtocolEngineImpl extends ProtocolEngineImpl { @@ -32,12 +36,15 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { @Inject ForumProtocolEngineImpl(DatabaseComponent db, - ClientHelper clientHelper, MessageEncoder messageEncoder, - MessageParser messageParser, MessageTracker messageTracker, - Clock clock, ForumManager forumManager, + ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, + MessageEncoder messageEncoder, MessageParser messageParser, + MessageTracker messageTracker, Clock clock, + ForumManager forumManager, InvitationFactory invitationFactory) { - super(db, clientHelper, messageEncoder, messageParser, messageTracker, - clock); + super(db, clientHelper, clientVersioningManager, messageEncoder, + messageParser, messageTracker, clock, CLIENT_ID, + CLIENT_VERSION); this.forumManager = forumManager; this.invitationFactory = invitationFactory; } @@ -46,8 +53,8 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { Event getInvitationRequestReceivedEvent(InviteMessage m, ContactId contactId, boolean available, boolean canBeOpened) { InvitationRequest request = invitationFactory - .createInvitationRequest(false, false, true, false, m, - contactId, available, canBeOpened); + .createInvitationRequest(false, false, true, false, m, + contactId, available, canBeOpened); return new ForumInvitationRequestReceivedEvent(m.getShareable(), contactId, request); } @@ -74,7 +81,7 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { @Override protected ClientId getShareableClientId() { - return ForumManager.CLIENT_ID; + return CLIENT_ID; } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java index 528743b9c..2f1ac5efb 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java @@ -8,9 +8,11 @@ import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumInvitationResponse; +import org.briarproject.briar.api.forum.ForumManager; import org.briarproject.briar.api.forum.ForumManager.RemoveForumHook; import org.briarproject.briar.api.forum.ForumSharingManager; @@ -22,15 +24,16 @@ class ForumSharingManagerImpl extends SharingManagerImpl @Inject ForumSharingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageParser messageParser, SessionEncoder sessionEncoder, SessionParser sessionParser, MessageTracker messageTracker, ContactGroupFactory contactGroupFactory, ProtocolEngine engine, InvitationFactory invitationFactory) { - super(db, clientHelper, metadataParser, messageParser, sessionEncoder, - sessionParser, messageTracker, contactGroupFactory, engine, - invitationFactory); + super(db, clientHelper, clientVersioningManager, metadataParser, + messageParser, sessionEncoder, sessionParser, messageTracker, + contactGroupFactory, engine, invitationFactory); } @Override @@ -43,6 +46,16 @@ class ForumSharingManagerImpl extends SharingManagerImpl return CLIENT_VERSION; } + @Override + protected ClientId getShareableClientId() { + return ForumManager.CLIENT_ID; + } + + @Override + protected int getShareableClientVersion() { + return ForumManager.CLIENT_VERSION; + } + @Override public void removingForum(Transaction txn, Forum f) throws DbException { removingShareable(txn, f); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java index e6a7976d5..6097c61aa 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java @@ -11,6 +11,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.GroupId; @@ -52,19 +53,27 @@ abstract class ProtocolEngineImpl protected final ClientHelper clientHelper; protected final MessageParser messageParser; + private final ClientVersioningManager clientVersioningManager; private final MessageEncoder messageEncoder; private final MessageTracker messageTracker; private final Clock clock; + private final ClientId shareableClientId; + private final int shareableClientVersion; ProtocolEngineImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MessageEncoder messageEncoder, MessageParser messageParser, - MessageTracker messageTracker, Clock clock) { + MessageTracker messageTracker, Clock clock, + ClientId shareableClientId, int shareableClientVersion) { this.db = db; this.clientHelper = clientHelper; + this.clientVersioningManager = clientVersioningManager; this.messageEncoder = messageEncoder; this.messageParser = messageParser; this.messageTracker = messageTracker; this.clock = clock; + this.shareableClientId = shareableClientId; + this.shareableClientVersion = shareableClientVersion; } @Override @@ -598,9 +607,13 @@ abstract class ProtocolEngineImpl } private void setShareableVisibility(Transaction txn, Session session, - Visibility v) throws DbException, FormatException { + Visibility preferred) throws DbException, FormatException { + // Apply min of preferred visibility and client's visibility ContactId contactId = getContactId(txn, session.getContactGroupId()); - db.setGroupVisibility(txn, contactId, session.getShareableId(), v); + Visibility client = clientVersioningManager.getClientVisibility(txn, + contactId, shareableClientId, shareableClientVersion); + Visibility min = Visibility.min(preferred, client); + db.setGroupVisibility(txn, contactId, session.getShareableId(), min); } private ContactId getContactId(Transaction txn, GroupId contactGroupId) diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java index 7cf2bf139..641731a4a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java @@ -9,6 +9,7 @@ import javax.inject.Inject; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_INVITE_TIMESTAMP; +import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_IS_SESSION; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LOCAL_TIMESTAMP; @@ -27,6 +28,7 @@ class SessionEncoderImpl implements SessionEncoder { @Override public BdfDictionary encodeSession(Session s) { BdfDictionary d = new BdfDictionary(); + d.put(SESSION_KEY_IS_SESSION, true); d.put(SESSION_KEY_SESSION_ID, s.getShareableId()); d.put(SESSION_KEY_SHAREABLE_ID, s.getShareableId()); MessageId lastLocalMessageId = s.getLastLocalMessageId(); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java index a82aed3ec..eec97355f 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java @@ -11,6 +11,8 @@ interface SessionParser { BdfDictionary getSessionQuery(SessionId s); + BdfDictionary getAllSessionsQuery(); + Session parseSession(GroupId contactGroupId, BdfDictionary d) throws FormatException; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java index 62d9c44b1..ee0c06f61 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java @@ -13,6 +13,7 @@ import javax.annotation.concurrent.Immutable; import javax.inject.Inject; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_INVITE_TIMESTAMP; +import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_IS_SESSION; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LOCAL_TIMESTAMP; @@ -33,6 +34,11 @@ class SessionParserImpl implements SessionParser { return BdfDictionary.of(new BdfEntry(SESSION_KEY_SESSION_ID, s)); } + @Override + public BdfDictionary getAllSessionsQuery() { + return BdfDictionary.of(new BdfEntry(SESSION_KEY_IS_SESSION, true)); + } + @Override public Session parseSession(GroupId contactGroupId, BdfDictionary d) throws FormatException { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java index d98099e27..f2522d1a9 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java @@ -18,6 +18,7 @@ interface SharingConstants { String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted"; // Session keys + String SESSION_KEY_IS_SESSION = "isSession"; String SESSION_KEY_STATE = "state"; String SESSION_KEY_SESSION_ID = "sessionId"; String SESSION_KEY_SHAREABLE_ID = "shareableId"; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index 711e3875e..d249fc1f6 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -16,7 +16,10 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Client; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; +import org.briarproject.bramble.api.sync.ClientVersioningManager.ClientVersioningHook; import org.briarproject.bramble.api.sync.Group; +import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; @@ -37,9 +40,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.logging.Logger; import javax.annotation.Nullable; +import static java.util.logging.Level.INFO; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.briar.sharing.MessageType.ABORT; import static org.briarproject.briar.sharing.MessageType.ACCEPT; @@ -52,8 +57,13 @@ import static org.briarproject.briar.sharing.State.SHARING; @NotNullByDefault abstract class SharingManagerImpl extends ConversationClientImpl - implements SharingManager, Client, ContactHook { + implements SharingManager, Client, ContactHook, + ClientVersioningHook { + private static final Logger LOG = + Logger.getLogger(SharingManagerImpl.class.getName()); + + private final ClientVersioningManager clientVersioningManager; private final MessageParser messageParser; private final SessionEncoder sessionEncoder; private final SessionParser sessionParser; @@ -62,12 +72,14 @@ abstract class SharingManagerImpl private final InvitationFactory invitationFactory; SharingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageParser messageParser, SessionEncoder sessionEncoder, SessionParser sessionParser, MessageTracker messageTracker, ContactGroupFactory contactGroupFactory, ProtocolEngine engine, InvitationFactory invitationFactory) { super(db, clientHelper, metadataParser, messageTracker); + this.clientVersioningManager = clientVersioningManager; this.messageParser = messageParser; this.sessionEncoder = sessionEncoder; this.sessionParser = sessionParser; @@ -80,6 +92,10 @@ abstract class SharingManagerImpl protected abstract int getClientVersion(); + protected abstract ClientId getShareableClientId(); + + protected abstract int getShareableClientVersion(); + @Override public void createLocalState(Transaction txn) throws DbException { // Create a local group to indicate that we've set this client up @@ -93,18 +109,22 @@ abstract class SharingManagerImpl @Override public void addingContact(Transaction txn, Contact c) throws DbException { + // Create a group to share with the contact + Group g = getContactGroup(c); + // Store the group and share it with the contact + db.addGroup(txn, g); + Visibility client = clientVersioningManager.getClientVisibility(txn, + c.getId(), getClientId(), getClientVersion()); + if (LOG.isLoggable(INFO)) + LOG.info("Applying visibility " + client + " to new contact group"); + db.setGroupVisibility(txn, c.getId(), g.getId(), client); + // Attach the contact ID to the group + BdfDictionary meta = new BdfDictionary(); + meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt()); try { - // Create a group to share with the contact - Group g = getContactGroup(c); - // Store the group and share it with the contact - db.addGroup(txn, g); - db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED); - // Attach the contact ID to the group - BdfDictionary meta = new BdfDictionary(); - meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt()); clientHelper.mergeGroupMetadata(txn, g.getId(), meta); } catch (FormatException e) { - throw new DbException(e); + throw new AssertionError(e); } } @@ -156,9 +176,13 @@ abstract class SharingManagerImpl getSessionId(shareable.getId())); if (existingSession != null) return; - // Add and share the shareable with the contact + // Add the shareable db.addGroup(txn, shareable.getGroup()); - db.setGroupVisibility(txn, c.getId(), shareable.getId(), SHARED); + + // Apply the client's visibility + Visibility client = clientVersioningManager.getClientVisibility(txn, + c.getId(), getShareableClientId(), getShareableClientVersion()); + db.setGroupVisibility(txn, c.getId(), shareable.getId(), client); // Initialize session in sharing state Session session = new Session(SHARING, contactGroupId, @@ -420,6 +444,7 @@ abstract class SharingManagerImpl Transaction txn = db.startTransaction(true); try { for (Contact c : db.getContacts(txn)) { + // FIXME: Check the session for the preferred visibility? if (db.getGroupVisibility(txn, c.getId(), g) == SHARED) contacts.add(c); } @@ -480,6 +505,58 @@ abstract class SharingManagerImpl } } + @Override + public void onClientVisibilityChanging(Transaction txn, Contact c, + Visibility v) throws DbException { + // Apply the client's visibility to the contact group + Group g = getContactGroup(c); + if (LOG.isLoggable(INFO)) + LOG.info("Applying visibility " + v + " to contact group"); + db.setGroupVisibility(txn, c.getId(), g.getId(), v); + } + + ClientVersioningHook getShareableClientVersioningHook() { + return this::onShareableClientVisibilityChanging; + } + + // Versioning hook for the shareable client + private void onShareableClientVisibilityChanging(Transaction txn, Contact c, + Visibility client) throws DbException { + try { + Collection shareables = db.getGroups(txn, + getShareableClientId(), getShareableClientVersion()); + Map m = getPreferredVisibilities(txn, c); + for (Group g : shareables) { + Visibility preferred = m.get(g.getId()); + if (preferred == null) continue; // No session for this group + // Apply min of preferred visibility and client's visibility + Visibility min = Visibility.min(preferred, client); + if (LOG.isLoggable(INFO)) { + LOG.info("Applying visibility " + min + + " to shareable, preferred " + preferred + + ", client" + client); + } + db.setGroupVisibility(txn, c.getId(), g.getId(), min); + } + } catch (FormatException e) { + throw new DbException(e); + } + } + + private Map getPreferredVisibilities(Transaction txn, + Contact c) throws DbException, FormatException { + GroupId contactGroupId = getContactGroup(c).getId(); + BdfDictionary query = sessionParser.getAllSessionsQuery(); + Map results = clientHelper + .getMessageMetadataAsDictionary(txn, contactGroupId, query); + Map m = new HashMap<>(); + for (BdfDictionary d : results.values()) { + Session s = sessionParser.parseSession(contactGroupId, d); + m.put(s.getShareableId(), s.getState().getVisibility()); + } + return m; + } + private static class StoredSession { private final MessageId storageId; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java index 4dfe78d8d..b31bfe68c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java @@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.ValidationManager; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.blog.Blog; @@ -73,6 +74,7 @@ public class SharingModule { LifecycleManager lifecycleManager, ContactManager contactManager, ValidationManager validationManager, ConversationManager conversationManager, BlogManager blogManager, + ClientVersioningManager clientVersioningManager, BlogSharingManagerImpl blogSharingManager) { lifecycleManager.registerClient(blogSharingManager); contactManager.registerContactHook(blogSharingManager); @@ -81,6 +83,18 @@ public class SharingModule { blogSharingManager); conversationManager.registerConversationClient(blogSharingManager); blogManager.registerRemoveBlogHook(blogSharingManager); + clientVersioningManager.registerClient(BlogSharingManager.CLIENT_ID, + BlogSharingManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + BlogSharingManager.CLIENT_ID, BlogSharingManager.CLIENT_VERSION, + blogSharingManager); + // The blog sharing manager handles client visibility changes for the + // blog manager + clientVersioningManager.registerClient(BlogManager.CLIENT_ID, + BlogManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + BlogManager.CLIENT_ID, BlogManager.CLIENT_VERSION, + blogSharingManager.getShareableClientVersioningHook()); return blogSharingManager; } @@ -123,6 +137,7 @@ public class SharingModule { LifecycleManager lifecycleManager, ContactManager contactManager, ValidationManager validationManager, ConversationManager conversationManager, ForumManager forumManager, + ClientVersioningManager clientVersioningManager, ForumSharingManagerImpl forumSharingManager) { lifecycleManager.registerClient(forumSharingManager); contactManager.registerContactHook(forumSharingManager); @@ -131,6 +146,18 @@ public class SharingModule { ForumSharingManager.CLIENT_VERSION, forumSharingManager); conversationManager.registerConversationClient(forumSharingManager); forumManager.registerRemoveForumHook(forumSharingManager); + clientVersioningManager.registerClient(ForumSharingManager.CLIENT_ID, + ForumSharingManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + ForumSharingManager.CLIENT_ID, + ForumSharingManager.CLIENT_VERSION, forumSharingManager); + // The forum sharing manager handles client visibility changes for the + // forum manager + clientVersioningManager.registerClient(ForumManager.CLIENT_ID, + ForumManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + ForumManager.CLIENT_ID, ForumManager.CLIENT_VERSION, + forumSharingManager.getShareableClientVersioningHook()); return forumSharingManager; } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/State.java b/briar-core/src/main/java/org/briarproject/briar/sharing/State.java index ade7d7a24..2d0ed9766 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/State.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/State.java @@ -2,26 +2,41 @@ package org.briarproject.briar.sharing; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.sync.Group.Visibility; import javax.annotation.concurrent.Immutable; +import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; +import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; +import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; + @Immutable @NotNullByDefault enum State { - START(0), LOCAL_INVITED(1), REMOTE_INVITED(2), SHARING(3), LOCAL_LEFT(4), - REMOTE_HANGING(5); + START(0, INVISIBLE), + LOCAL_INVITED(1, INVISIBLE), + REMOTE_INVITED(2, VISIBLE), + SHARING(3, SHARED), + LOCAL_LEFT(4, INVISIBLE), + REMOTE_HANGING(5, INVISIBLE); private final int value; + private final Visibility visibility; - State(int value) { + State(int value, Visibility visibility) { this.value = value; + this.visibility = visibility; } public int getValue() { return value; } + public Visibility getVisibility() { + return visibility; + } + public boolean canInvite() { return this == START; } diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java index 8a7a3775f..5b109533c 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java @@ -14,6 +14,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; @@ -24,7 +25,6 @@ import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.SessionId; import org.jmock.Expectations; -import org.jmock.Mockery; import org.junit.Test; import java.util.Collection; @@ -44,12 +44,13 @@ import static org.briarproject.briar.sharing.SharingConstants.GROUP_KEY_CONTACT_ public class BlogSharingManagerImplTest extends BrambleMockTestCase { - private final Mockery context = new Mockery(); private final BlogSharingManagerImpl blogSharingManager; private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final IdentityManager identityManager = context.mock(IdentityManager.class); private final ClientHelper clientHelper = context.mock(ClientHelper.class); + private final ClientVersioningManager clientVersioningManager = + context.mock(ClientVersioningManager.class); private final SessionEncoder sessionEncoder = context.mock(SessionEncoder.class); private final SessionParser sessionParser = @@ -80,14 +81,15 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase { @SuppressWarnings("unchecked") public BlogSharingManagerImplTest() { MetadataParser metadataParser = context.mock(MetadataParser.class); - MessageTracker messageTracker = context.mock(MessageTracker.class); MessageParser messageParser = context.mock(MessageParser.class); + MessageTracker messageTracker = context.mock(MessageTracker.class); InvitationFactory invitationFactory = context.mock(InvitationFactory.class); blogSharingManager = new BlogSharingManagerImpl(db, clientHelper, - metadataParser, messageParser, sessionEncoder, sessionParser, - messageTracker, contactGroupFactory, engine, invitationFactory, - identityManager, blogManager); + clientVersioningManager, metadataParser, messageParser, + sessionEncoder, sessionParser, messageTracker, + contactGroupFactory, engine, invitationFactory, identityManager, + blogManager); } @Test @@ -124,6 +126,9 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase { CLIENT_VERSION, contact); will(returnValue(contactGroup)); oneOf(db).addGroup(txn, contactGroup); + oneOf(clientVersioningManager).getClientVisibility(txn, contactId, + CLIENT_ID, CLIENT_VERSION); + will(returnValue(SHARED)); oneOf(db).setGroupVisibility(txn, contactId, contactGroup.getId(), SHARED); // Attach the contact ID to the group @@ -207,6 +212,10 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase { will(returnValue(sessions)); if (sessions.size() == 0) { oneOf(db).addGroup(txn, blog.getGroup()); + oneOf(clientVersioningManager).getClientVisibility(txn, + contactId, BlogManager.CLIENT_ID, + BlogManager.CLIENT_VERSION); + will(returnValue(SHARED)); oneOf(db).setGroupVisibility(txn, contact.getId(), blog.getGroup().getId(), SHARED); oneOf(clientHelper) diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java index ebd3f2238..bb955313b 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java @@ -256,6 +256,8 @@ public abstract class BriarIntegrationTest