From 61e18f104ef5a6f48efaab538ee5d8db61b6c6fe Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 5 Sep 2018 15:22:12 -0300 Subject: [PATCH] Unify all private message responses in one PrivateResponse class This also adds `Shareable`s to invitation response which is a precondition for #561 --- .../android/blog/BlogControllerImpl.java | 6 +- .../android/contact/ContactListFragment.java | 4 +- .../android/contact/ConversationActivity.java | 64 +++--------- .../android/contact/ConversationItem.java | 97 +++++++++---------- .../android/forum/ForumControllerImpl.java | 2 +- .../conversation/GroupControllerImpl.java | 2 +- .../api/blog/BlogInvitationResponse.java | 8 +- .../BlogInvitationResponseReceivedEvent.java | 3 +- .../api/forum/ForumInvitationResponse.java | 8 +- .../introduction/IntroductionResponse.java | 40 ++------ .../briar/api/messaging/PrivateResponse.java | 40 ++++++++ .../GroupInvitationResponseReceivedEvent.java | 7 +- .../invitation/GroupInvitationResponse.java | 9 +- .../briar/api/sharing/InvitationResponse.java | 41 -------- .../InvitationResponseReceivedEvent.java | 12 ++- .../introduction/AbstractProtocolEngine.java | 8 +- .../introduction/IntroductionManagerImpl.java | 7 +- .../invitation/CreatorProtocolEngine.java | 14 ++- .../GroupInvitationManagerImpl.java | 53 ++++++---- .../sharing/BlogInvitationFactoryImpl.java | 8 +- .../briar/sharing/BlogMessageParserImpl.java | 2 +- .../briar/sharing/BlogProtocolEngineImpl.java | 8 +- .../sharing/ForumInvitationFactoryImpl.java | 7 +- .../briar/sharing/ForumMessageParserImpl.java | 2 +- .../sharing/ForumProtocolEngineImpl.java | 8 +- .../briar/sharing/InvitationFactory.java | 7 +- .../briar/sharing/MessageParser.java | 2 + .../briar/sharing/MessageParserImpl.java | 3 - .../briar/sharing/ProtocolEngineImpl.java | 38 +++++--- .../briar/sharing/SharingManagerImpl.java | 45 +++++---- .../IntroductionIntegrationTest.java | 12 +-- .../invitation/CreatorProtocolEngineTest.java | 4 + .../GroupInvitationIntegrationTest.java | 51 ++++++++-- .../GroupInvitationManagerImplTest.java | 6 ++ .../sharing/BlogSharingIntegrationTest.java | 8 +- .../sharing/ForumSharingIntegrationTest.java | 10 +- .../briar/test/BriarIntegrationTest.java | 18 ++++ 37 files changed, 357 insertions(+), 307 deletions(-) create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateResponse.java delete mode 100644 briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java index 6b29f6f44..d62a52c18 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java @@ -25,7 +25,7 @@ import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent; import org.briarproject.briar.api.blog.event.BlogPostAddedEvent; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent; import java.util.ArrayList; @@ -107,8 +107,8 @@ class BlogControllerImpl extends BaseControllerImpl } else if (e instanceof BlogInvitationResponseReceivedEvent) { BlogInvitationResponseReceivedEvent b = (BlogInvitationResponseReceivedEvent) e; - InvitationResponse r = b.getResponse(); - if (r.getShareableId().equals(groupId) && r.wasAccepted()) { + PrivateResponse r = b.getResponse(); + if (r.getObject().getId().equals(groupId) && r.wasAccepted()) { LOG.info("Blog invitation accepted"); onBlogInvitationAccepted(b.getContactId()); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java index 95e8c3067..dea7d542c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java @@ -44,8 +44,8 @@ import org.briarproject.briar.api.introduction.event.IntroductionResponseReceive import org.briarproject.briar.api.messaging.ConversationManager; import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateRequest; +import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent; -import org.briarproject.briar.api.sharing.InvitationResponse; import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent; import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; @@ -277,7 +277,7 @@ public class ContactListFragment extends BaseFragment implements EventListener { LOG.info("Invitation response received, updating item"); InvitationResponseReceivedEvent m = (InvitationResponseReceivedEvent) e; - InvitationResponse ir = m.getResponse(); + PrivateResponse ir = m.getResponse(); updateItem(m.getContactId(), ir); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java index f462f363d..07270b460 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java @@ -71,9 +71,9 @@ import org.briarproject.briar.api.messaging.PrivateMessage; import org.briarproject.briar.api.messaging.PrivateMessageFactory; import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateRequest; +import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; -import org.briarproject.briar.api.sharing.InvitationResponse; import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent; import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; import org.thoughtcrime.securesms.components.util.FutureTaskListener; @@ -424,7 +424,7 @@ public class ConversationActivity extends BriarActivity item = ConversationItem .from(this, contactName, (PrivateRequest) i); } else { - InvitationResponse r = (InvitationResponse) i; + PrivateResponse r = (PrivateResponse) i; item = ConversationItem.from(this, contactName, r); } items.add(item); @@ -507,16 +507,16 @@ public class ConversationActivity extends BriarActivity (IntroductionRequestReceivedEvent) e; if (event.getContactId().equals(contactId)) { LOG.info("Introduction request received, adding..."); - IntroductionRequest ir = event.getIntroductionRequest(); - handleIntroductionRequest(ir); + PrivateRequest ir = event.getIntroductionRequest(); + handlePrivateRequest(ir); } } else if (e instanceof IntroductionResponseReceivedEvent) { IntroductionResponseReceivedEvent event = (IntroductionResponseReceivedEvent) e; if (event.getContactId().equals(contactId)) { LOG.info("Introduction response received, adding..."); - IntroductionResponse ir = event.getIntroductionResponse(); - handleIntroductionResponse(ir); + PrivateResponse ir = event.getIntroductionResponse(); + handlePrivateResponse(ir); } } else if (e instanceof InvitationRequestReceivedEvent) { InvitationRequestReceivedEvent event = @@ -524,15 +524,15 @@ public class ConversationActivity extends BriarActivity if (event.getContactId().equals(contactId)) { LOG.info("Invitation received, adding..."); PrivateRequest ir = event.getRequest(); - handleInvitationRequest(ir); + handlePrivateRequest(ir); } } else if (e instanceof InvitationResponseReceivedEvent) { InvitationResponseReceivedEvent event = (InvitationResponseReceivedEvent) e; if (event.getContactId().equals(contactId)) { LOG.info("Invitation response received, adding..."); - InvitationResponse ir = event.getResponse(); - handleInvitationResponse(ir); + PrivateResponse ir = event.getResponse(); + handlePrivateResponse(ir); } } } @@ -546,7 +546,7 @@ public class ConversationActivity extends BriarActivity }); } - private void handleIntroductionRequest(IntroductionRequest m) { + private void handlePrivateRequest(PrivateRequest m) { getContactNameTask().addListener(new FutureTaskListener() { @Override public void onSuccess(String contactName) { @@ -565,7 +565,7 @@ public class ConversationActivity extends BriarActivity }); } - private void handleIntroductionResponse(IntroductionResponse m) { + private void handlePrivateResponse(PrivateResponse m) { getContactNameTask().addListener(new FutureTaskListener() { @Override public void onSuccess(String contactName) { @@ -584,46 +584,8 @@ public class ConversationActivity extends BriarActivity }); } - private void handleInvitationRequest(PrivateRequest m) { - getContactNameTask().addListener(new FutureTaskListener() { - @Override - public void onSuccess(String contactName) { - runOnUiThreadUnlessDestroyed(() -> { - ConversationItem item = ConversationItem - .from(ConversationActivity.this, contactName, m); - addConversationItem(item); - }); - } - - @Override - public void onFailure(Throwable exception) { - runOnUiThreadUnlessDestroyed( - () -> handleDbException((DbException) exception)); - } - }); - } - - private void handleInvitationResponse(InvitationResponse m) { - getContactNameTask().addListener(new FutureTaskListener() { - @Override - public void onSuccess(String contactName) { - runOnUiThreadUnlessDestroyed(() -> { - ConversationItem item = ConversationItem - .from(ConversationActivity.this, contactName, m); - addConversationItem(item); - }); - } - - @Override - public void onFailure(Throwable exception) { - runOnUiThreadUnlessDestroyed( - () -> handleDbException((DbException) exception)); - } - }); - } - - private void markMessages(Collection messageIds, - boolean sent, boolean seen) { + private void markMessages(Collection messageIds, boolean sent, + boolean seen) { runOnUiThreadUnlessDestroyed(() -> { adapter.incrementRevision(); Set messages = new HashSet<>(messageIds); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java index 6ee0505d4..0177bed10 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java @@ -17,9 +17,9 @@ import org.briarproject.briar.api.introduction.IntroductionRequest; import org.briarproject.briar.api.introduction.IntroductionResponse; import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateRequest; +import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse; -import org.briarproject.briar.api.sharing.InvitationResponse; import org.briarproject.briar.api.sharing.Shareable; import javax.annotation.Nullable; @@ -87,46 +87,6 @@ abstract class ConversationItem { } } - static ConversationItem from(Context ctx, String contactName, - IntroductionResponse ir) { - if (ir.isLocal()) { - String text; - if (ir.wasAccepted()) { - text = ctx.getString( - R.string.introduction_response_accepted_sent, - ir.getName()); - text += "\n\n" + ctx.getString( - R.string.introduction_response_accepted_sent_info, - ir.getName()); - } else { - text = ctx.getString( - R.string.introduction_response_declined_sent, - ir.getName()); - } - return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(), - text, null, ir.getTimestamp(), ir.isSent(), ir.isSeen()); - } else { - String text; - if (ir.wasAccepted()) { - text = ctx.getString( - R.string.introduction_response_accepted_received, - contactName, ir.getName()); - } else { - if (ir.isIntroducer()) { - text = ctx.getString( - R.string.introduction_response_declined_received, - contactName, ir.getName()); - } else { - text = ctx.getString( - R.string.introduction_response_declined_received_by_introducee, - contactName, ir.getName()); - } - } - return new ConversationNoticeInItem(ir.getId(), ir.getGroupId(), - text, null, ir.getTimestamp(), ir.isRead()); - } - } - static ConversationItem from(Context ctx, String contactName, PrivateRequest ir) { if (ir.isLocal()) { @@ -196,7 +156,44 @@ abstract class ConversationItem { } static ConversationItem from(Context ctx, String contactName, - InvitationResponse ir) { + IntroductionResponse ir) { + if (ir.isLocal()) { + String text; + if (ir.wasAccepted()) { + text = ctx.getString( + R.string.introduction_response_accepted_sent, + ir.getObject().getName()); + text += "\n\n" + ctx.getString( + R.string.introduction_response_accepted_sent_info, + ir.getObject().getName()); + } else { + text = ctx.getString( + R.string.introduction_response_declined_sent, + ir.getObject().getName()); + } + return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(), + text, null, ir.getTimestamp(), ir.isSent(), ir.isSeen()); + } else { + @StringRes int res; + if (ir.wasAccepted()) { + res = R.string.introduction_response_accepted_received; + } else { + if (ir.getObject().isIntroducer()) { + res = R.string.introduction_response_declined_received; + } else { + res = + R.string.introduction_response_declined_received_by_introducee; + } + } + String text = + ctx.getString(res, contactName, ir.getObject().getName()); + return new ConversationNoticeInItem(ir.getId(), ir.getGroupId(), + text, null, ir.getTimestamp(), ir.isRead()); + } + } + + static ConversationItem from(Context ctx, String contactName, + PrivateResponse ir) { @StringRes int res; if (ir.isLocal()) { if (ir.wasAccepted()) { @@ -208,7 +205,7 @@ abstract class ConversationItem { res = R.string.groups_invitations_response_accepted_sent; } else { throw new IllegalArgumentException( - "Unknown InvitationResponse"); + "Unknown PrivateResponse"); } } else { if (ir instanceof ForumInvitationResponse) { @@ -219,7 +216,7 @@ abstract class ConversationItem { res = R.string.groups_invitations_response_declined_sent; } else { throw new IllegalArgumentException( - "Unknown InvitationResponse"); + "Unknown PrivateResponse"); } } String text = ctx.getString(res, contactName); @@ -235,7 +232,7 @@ abstract class ConversationItem { res = R.string.groups_invitations_response_accepted_received; } else { throw new IllegalArgumentException( - "Unknown InvitationResponse"); + "Unknown PrivateResponse"); } } else { if (ir instanceof ForumInvitationResponse) { @@ -246,7 +243,7 @@ abstract class ConversationItem { res = R.string.groups_invitations_response_declined_received; } else { throw new IllegalArgumentException( - "Unknown InvitationResponse"); + "Unknown PrivateResponse"); } } String text = ctx.getString(res, contactName); @@ -261,14 +258,12 @@ abstract class ConversationItem { * PrivateMessageHeader. **/ static ConversationItem from(Context ctx, PrivateMessageHeader h) { - if(h instanceof IntroductionRequest) { - return from(ctx, "", (IntroductionRequest) h); - } else if(h instanceof IntroductionResponse) { + if(h instanceof IntroductionResponse) { return from(ctx, "", (IntroductionResponse) h); } else if(h instanceof PrivateRequest) { return from(ctx, "", (PrivateRequest) h); - } else if(h instanceof InvitationResponse) { - return from(ctx, "", (InvitationResponse) h); + } else if(h instanceof PrivateResponse) { + return from(ctx, "", (PrivateResponse) h); } else { return from(h); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java index 91d0cf596..ea8365c1a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java @@ -86,7 +86,7 @@ class ForumControllerImpl extends (ForumInvitationResponseReceivedEvent) e; ForumInvitationResponse r = (ForumInvitationResponse) f.getResponse(); - if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) { + if (r.getObject().getId().equals(getGroupId()) && r.wasAccepted()) { LOG.info("Forum invitation was accepted"); onForumInvitationAccepted(f.getContactId()); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java index cc825d3b1..aa5d8c951 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java @@ -101,7 +101,7 @@ class GroupControllerImpl extends (GroupInvitationResponseReceivedEvent) e; GroupInvitationResponse r = (GroupInvitationResponse) g.getResponse(); - if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) { + if (getGroupId().equals(r.getObject().getId()) && r.wasAccepted()) { listener.runOnUiThreadUnlessDestroyed( () -> listener.onInvitationAccepted(g.getContactId())); } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java index 3183a37b0..b663e0a37 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java @@ -4,15 +4,15 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.client.SessionId; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; @NotNullByDefault -public class BlogInvitationResponse extends InvitationResponse { +public class BlogInvitationResponse extends PrivateResponse { public BlogInvitationResponse(MessageId id, GroupId groupId, long time, boolean local, boolean sent, boolean seen, boolean read, - SessionId sessionId, GroupId blogId, boolean accept) { - super(id, groupId, time, local, sent, seen, read, sessionId, blogId, + SessionId sessionId, Blog blog, boolean accept) { + super(id, groupId, time, local, sent, seen, read, sessionId, blog, accept); } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java index 0b9ae9005..ee9b22d1f 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java @@ -2,6 +2,7 @@ package org.briarproject.briar.api.blog.event; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.BlogInvitationResponse; import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; @@ -10,7 +11,7 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault public class BlogInvitationResponseReceivedEvent - extends InvitationResponseReceivedEvent { + extends InvitationResponseReceivedEvent { public BlogInvitationResponseReceivedEvent(ContactId contactId, BlogInvitationResponse response) { diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java index 9c44bba71..302f4317a 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java @@ -4,18 +4,18 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.client.SessionId; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -public class ForumInvitationResponse extends InvitationResponse { +public class ForumInvitationResponse extends PrivateResponse { public ForumInvitationResponse(MessageId id, GroupId groupId, long time, boolean local, boolean sent, boolean seen, boolean read, - SessionId sessionId, GroupId forumId, boolean accept) { - super(id, groupId, time, local, sent, seen, read, sessionId, forumId, + SessionId sessionId, Forum forum, boolean accept) { + super(id, groupId, time, local, sent, seen, read, sessionId, forum, accept); } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java index 5ac474d57..f52fbe38b 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java @@ -4,45 +4,19 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.client.SessionId; -import org.briarproject.briar.api.messaging.PrivateMessageHeader; +import org.briarproject.briar.api.messaging.PrivateResponse; import javax.annotation.concurrent.Immutable; -import static org.briarproject.briar.api.introduction.Role.INTRODUCER; - @Immutable @NotNullByDefault -public class IntroductionResponse extends PrivateMessageHeader { +public class IntroductionResponse extends PrivateResponse { - private final SessionId sessionId; - private final String name; - private final Role role; - private final boolean accepted; - - public IntroductionResponse(SessionId sessionId, MessageId messageId, - GroupId groupId, Role role, long time, boolean local, boolean sent, - boolean seen, boolean read, String name, boolean accepted) { - super(messageId, groupId, time, local, sent, seen, read); - this.sessionId = sessionId; - this.name = name; - this.role = role; - this.accepted = accepted; - } - - public SessionId getSessionId() { - return sessionId; - } - - public String getName() { - return name; - } - - public boolean isIntroducer() { - return role == INTRODUCER; - } - - public boolean wasAccepted() { - return accepted; + public IntroductionResponse(MessageId messageId, GroupId groupId, long time, + boolean local, boolean sent, boolean seen, boolean read, + SessionId sessionId, Introduction introduction, boolean accepted) { + super(messageId, groupId, time, local, sent, seen, read, sessionId, + introduction, accepted); } } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateResponse.java new file mode 100644 index 000000000..bb7754789 --- /dev/null +++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateResponse.java @@ -0,0 +1,40 @@ +package org.briarproject.briar.api.messaging; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; +import org.briarproject.briar.api.client.SessionId; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +public abstract class PrivateResponse + extends PrivateMessageHeader { + + private final SessionId sessionId; + private final O object; + private final boolean accepted; + + public PrivateResponse(MessageId id, GroupId groupId, long time, + boolean local, boolean sent, boolean seen, boolean read, + SessionId sessionId, O object, boolean accepted) { + super(id, groupId, time, local, sent, seen, read); + this.sessionId = sessionId; + this.object = object; + this.accepted = accepted; + } + + public SessionId getSessionId() { + return sessionId; + } + + public O getObject() { + return object; + } + + public boolean wasAccepted() { + return accepted; + } + +} diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java index 705c93074..e1af29e15 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java @@ -2,7 +2,8 @@ package org.briarproject.briar.api.privategroup.event; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; +import org.briarproject.briar.api.privategroup.PrivateGroup; import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; import javax.annotation.concurrent.Immutable; @@ -10,10 +11,10 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault public class GroupInvitationResponseReceivedEvent - extends InvitationResponseReceivedEvent { + extends InvitationResponseReceivedEvent { public GroupInvitationResponseReceivedEvent(ContactId contactId, - InvitationResponse response) { + PrivateResponse response) { super(contactId, response); } } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java index 8531f502d..fb8dbf608 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java @@ -4,19 +4,20 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.client.SessionId; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; +import org.briarproject.briar.api.privategroup.PrivateGroup; import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -public class GroupInvitationResponse extends InvitationResponse { +public class GroupInvitationResponse extends PrivateResponse { public GroupInvitationResponse(MessageId id, GroupId groupId, long time, boolean local, boolean sent, boolean seen, boolean read, - SessionId sessionId, GroupId shareableId, boolean accept) { + SessionId sessionId, PrivateGroup privateGroup, boolean accept) { super(id, groupId, time, local, sent, seen, read, sessionId, - shareableId, accept); + privateGroup, accept); } } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java deleted file mode 100644 index f7afc699e..000000000 --- a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.briarproject.briar.api.sharing; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.api.sync.GroupId; -import org.briarproject.bramble.api.sync.MessageId; -import org.briarproject.briar.api.client.SessionId; -import org.briarproject.briar.api.messaging.PrivateMessageHeader; - -import javax.annotation.concurrent.Immutable; - -@Immutable -@NotNullByDefault -public abstract class InvitationResponse extends PrivateMessageHeader { - - private final SessionId sessionId; - private final GroupId shareableId; - private final boolean accept; - - public InvitationResponse(MessageId id, GroupId groupId, - long time, boolean local, boolean sent, boolean seen, - boolean read, SessionId sessionId, GroupId shareableId, - boolean accept) { - super(id, groupId, time, local, sent, seen, read); - this.sessionId = sessionId; - this.shareableId = shareableId; - this.accept = accept; - } - - public SessionId getSessionId() { - return sessionId; - } - - public boolean wasAccepted() { - return accept; - } - - public GroupId getShareableId() { - return shareableId; - } - -} diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java index ac9ebce86..85e15462c 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java @@ -3,19 +3,21 @@ package org.briarproject.briar.api.sharing.event; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; +import org.briarproject.briar.api.sharing.Shareable; import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -public abstract class InvitationResponseReceivedEvent extends Event { +public abstract class InvitationResponseReceivedEvent + extends Event { private final ContactId contactId; - private final InvitationResponse response; + private final PrivateResponse response; public InvitationResponseReceivedEvent(ContactId contactId, - InvitationResponse response) { + PrivateResponse response) { this.contactId = contactId; this.response = response; } @@ -24,7 +26,7 @@ public abstract class InvitationResponseReceivedEvent extends Event { return contactId; } - public InvitationResponse getResponse() { + public PrivateResponse getResponse() { return response; } } diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java index 03b3486ad..424ea2f39 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java @@ -20,6 +20,7 @@ import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.SessionId; +import org.briarproject.briar.api.introduction.Introduction; import org.briarproject.briar.api.introduction.IntroductionResponse; import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent; @@ -147,12 +148,13 @@ abstract class AbstractProtocolEngine void broadcastIntroductionResponseReceivedEvent(Transaction txn, Session s, AuthorId sender, Author otherAuthor, AbstractIntroductionMessage m) throws DbException { + Introduction introduction = new Introduction(otherAuthor, s.getRole()); AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId(); Contact c = contactManager.getContact(txn, sender, localAuthorId); IntroductionResponse response = - new IntroductionResponse(s.getSessionId(), m.getMessageId(), - m.getGroupId(), s.getRole(), m.getTimestamp(), false, - false, false, false, otherAuthor.getName(), + new IntroductionResponse(m.getMessageId(), m.getGroupId(), + m.getTimestamp(), false, false, false, false, + s.getSessionId(), introduction, m instanceof AcceptMessage); IntroductionResponseReceivedEvent e = new IntroductionResponseReceivedEvent(c.getId(), response); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java index 818043442..76cd52b92 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java @@ -509,9 +509,10 @@ class IntroductionManagerImpl extends ConversationClientImpl sessionId = session.getSessionId(); author = session.getRemote().author; } else throw new AssertionError(); - return new IntroductionResponse(sessionId, m, contactGroupId, - role, meta.getTimestamp(), meta.isLocal(), status.isSent(), - status.isSeen(), meta.isRead(), author.getName(), accept); + Introduction introduction = new Introduction(author, role); + return new IntroductionResponse(m, contactGroupId, meta.getTimestamp(), + meta.isLocal(), status.isSent(), status.isSeen(), meta.isRead(), + sessionId, introduction, accept); } private void removeSessionWithIntroducer(Transaction txn, diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java index 057c3420f..be9c4d326 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java @@ -15,6 +15,7 @@ import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.privategroup.GroupMessageFactory; +import org.briarproject.briar.api.privategroup.PrivateGroup; import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import org.briarproject.briar.api.privategroup.PrivateGroupManager; import org.briarproject.briar.api.privategroup.event.GroupInvitationResponseReceivedEvent; @@ -193,8 +194,10 @@ class CreatorProtocolEngine extends AbstractProtocolEngine { setPrivateGroupVisibility(txn, s, SHARED); // Broadcast an event ContactId contactId = getContactId(txn, m.getContactGroupId()); + PrivateGroup privateGroup = + privateGroupManager.getPrivateGroup(txn, m.getPrivateGroupId()); txn.attach(new GroupInvitationResponseReceivedEvent(contactId, - createInvitationResponse(m, contactId, true))); + createInvitationResponse(m, privateGroup, true))); // Move to the JOINED state return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(), sent.getId(), m.getId(), sent.getTimestamp(), @@ -215,8 +218,10 @@ class CreatorProtocolEngine extends AbstractProtocolEngine { m.getTimestamp(), false); // Broadcast an event ContactId contactId = getContactId(txn, m.getContactGroupId()); + PrivateGroup privateGroup = + privateGroupManager.getPrivateGroup(txn, m.getPrivateGroupId()); txn.attach(new GroupInvitationResponseReceivedEvent(contactId, - createInvitationResponse(m, contactId, false))); + createInvitationResponse(m, privateGroup, false))); // Move to the START state return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(), s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(), @@ -254,10 +259,11 @@ class CreatorProtocolEngine extends AbstractProtocolEngine { } private GroupInvitationResponse createInvitationResponse( - GroupInvitationMessage m, ContactId c, boolean accept) { + GroupInvitationMessage m, PrivateGroup privateGroup, + boolean accept) { SessionId sessionId = new SessionId(m.getPrivateGroupId().getBytes()); return new GroupInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, sessionId, - m.getPrivateGroupId(), accept); + privateGroup, accept); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java index 8d4d2a7d7..15b82bdd6 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java @@ -353,7 +353,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl private S handleAction(Transaction txn, LocalAction type, S session, ProtocolEngine engine) - throws DbException, FormatException { + throws DbException { if (type == LocalAction.INVITE) { throw new IllegalArgumentException(); } else if (type == LocalAction.JOIN) { @@ -392,23 +392,36 @@ class GroupInvitationManagerImpl extends ConversationClientImpl .getMessageMetadataAsDictionary(txn, contactGroupId, query); List messages = new ArrayList<>(results.size()); + // get invite message first and remember private groups + Map privateGroups = new HashMap<>(); for (Entry e : results.entrySet()) { MessageId m = e.getKey(); MessageMetadata meta = messageParser.parseMetadata(e.getValue()); - MessageStatus status = db.getMessageStatus(txn, c, m); MessageType type = meta.getMessageType(); - if (type == INVITE) { - messages.add(parseInvitationRequest(txn, c, contactGroupId, - m, meta, status)); - } else if (type == JOIN) { - messages.add( - parseInvitationResponse(c, contactGroupId, m, meta, - status, true)); + if (type != INVITE) continue; + MessageStatus status = db.getMessageStatus(txn, c, m); + GroupInvitationRequest invite = parseInvitationRequest(txn, + contactGroupId, m, meta, status); + messages.add(invite); + privateGroups.put(invite.getSessionId(), invite.getObject()); + } + for (Entry e : results.entrySet()) { + MessageId m = e.getKey(); + MessageMetadata meta = + messageParser.parseMetadata(e.getValue()); + MessageType type = meta.getMessageType(); + if (type == INVITE) continue; + MessageStatus status = db.getMessageStatus(txn, c, m); + SessionId sessionId = getSessionId(meta.getPrivateGroupId()); + PrivateGroup privateGroup = privateGroups.get(sessionId); + if (privateGroup == null) throw new AssertionError(); + if (type == JOIN) { + messages.add(parseInvitationResponse(contactGroupId, m, + meta, status, sessionId, privateGroup, true)); } else if (type == LEAVE) { - messages.add( - parseInvitationResponse(c, contactGroupId, m, meta, - status, false)); + messages.add(parseInvitationResponse(contactGroupId, m, + meta, status, sessionId, privateGroup, false)); } } return messages; @@ -418,9 +431,8 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } private GroupInvitationRequest parseInvitationRequest(Transaction txn, - ContactId c, GroupId contactGroupId, MessageId m, - MessageMetadata meta, MessageStatus status) - throws DbException, FormatException { + GroupId contactGroupId, MessageId m, MessageMetadata meta, + MessageStatus status) throws DbException, FormatException { SessionId sessionId = getSessionId(meta.getPrivateGroupId()); // Look up the invite message to get the details of the private group InviteMessage invite = messageParser.getInviteMessage(txn, m); @@ -436,15 +448,14 @@ class GroupInvitationManagerImpl extends ConversationClientImpl invite.getMessage(), meta.isAvailableToAnswer(), canBeOpened); } - private GroupInvitationResponse parseInvitationResponse(ContactId c, + private GroupInvitationResponse parseInvitationResponse( GroupId contactGroupId, MessageId m, MessageMetadata meta, - MessageStatus status, boolean accept) - throws DbException, FormatException { - SessionId sessionId = getSessionId(meta.getPrivateGroupId()); + MessageStatus status, SessionId sessionId, + PrivateGroup privateGroup, boolean accept) { return new GroupInvitationResponse(m, contactGroupId, meta.getTimestamp(), meta.isLocal(), status.isSent(), - status.isSeen(), meta.isRead(), sessionId, - meta.getPrivateGroupId(), accept); + status.isSeen(), meta.isRead(), sessionId, privateGroup, + accept); } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java index 9063ebcbc..693f0947c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java @@ -30,10 +30,10 @@ public class BlogInvitationFactoryImpl @Override public BlogInvitationResponse createInvitationResponse(MessageId id, GroupId contactGroupId, long time, boolean local, boolean sent, - boolean seen, boolean read, GroupId shareableId, boolean accept) { - SessionId sessionId = new SessionId(shareableId.getBytes()); - return new BlogInvitationResponse(id, contactGroupId, time, local, - sent, seen, read, sessionId, shareableId, accept); + boolean seen, boolean read, Blog blog, boolean accept) { + SessionId sessionId = new SessionId(blog.getId().getBytes()); + return new BlogInvitationResponse(id, contactGroupId, time, local, sent, + seen, read, sessionId, blog, accept); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java index a2fc9d95d..9bb080bb2 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java @@ -30,7 +30,7 @@ class BlogMessageParserImpl extends MessageParserImpl { } @Override - protected Blog createShareable(BdfList descriptor) throws FormatException { + public Blog createShareable(BdfList descriptor) throws FormatException { // Author, RSS BdfList authorList = descriptor.getList(0); boolean rssFeed = descriptor.getBoolean(1); 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 696ce5143..8df04ab0c 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 @@ -59,21 +59,21 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { @Override Event getInvitationResponseReceivedEvent(AcceptMessage m, - ContactId contactId) { + ContactId contactId, Blog shareable) { BlogInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, - m.getShareableId(), true); + shareable, true); return new BlogInvitationResponseReceivedEvent(contactId, response); } @Override Event getInvitationResponseReceivedEvent(DeclineMessage m, - ContactId contactId) { + ContactId contactId, Blog shareable) { BlogInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, - m.getShareableId(), true); + shareable, true); return new BlogInvitationResponseReceivedEvent(contactId, response); } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java index 758082933..cb95c3759 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java @@ -30,11 +30,10 @@ public class ForumInvitationFactoryImpl @Override public ForumInvitationResponse createInvitationResponse(MessageId id, GroupId contactGroupId, long time, boolean local, boolean sent, - boolean seen, boolean read, GroupId shareableId, - boolean accept) { - SessionId sessionId = new SessionId(shareableId.getBytes()); + boolean seen, boolean read, Forum forum, boolean accept) { + SessionId sessionId = new SessionId(forum.getId().getBytes()); return new ForumInvitationResponse(id, contactGroupId, time, local, - sent, seen, read, sessionId, shareableId, accept); + sent, seen, read, sessionId, forum, accept); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumMessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumMessageParserImpl.java index 44ef0d821..76e5569ba 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumMessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumMessageParserImpl.java @@ -24,7 +24,7 @@ class ForumMessageParserImpl extends MessageParserImpl { } @Override - protected Forum createShareable(BdfList descriptor) throws FormatException { + public Forum createShareable(BdfList descriptor) throws FormatException { // Name, salt String name = descriptor.getString(0); byte[] salt = descriptor.getRaw(1); 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 6ffad99d1..383090150 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 @@ -61,21 +61,21 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { @Override Event getInvitationResponseReceivedEvent(AcceptMessage m, - ContactId contactId) { + ContactId contactId, Forum shareable) { ForumInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, - m.getShareableId(), true); + shareable, true); return new ForumInvitationResponseReceivedEvent(contactId, response); } @Override Event getInvitationResponseReceivedEvent(DeclineMessage m, - ContactId contactId) { + ContactId contactId, Forum shareable) { ForumInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, - m.getShareableId(), true); + shareable, true); return new ForumInvitationResponseReceivedEvent(contactId, response); } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java index 361ab532f..3ceb94d7c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java @@ -4,10 +4,10 @@ import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.messaging.PrivateRequest; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.sharing.Shareable; -public interface InvitationFactory { +public interface InvitationFactory> { PrivateRequest createInvitationRequest(boolean local, boolean sent, boolean seen, boolean read, InviteMessage m, ContactId c, @@ -15,7 +15,6 @@ public interface InvitationFactory { MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException; + S createShareable(BdfList descriptor) throws FormatException; + InviteMessage getInviteMessage(Transaction txn, MessageId m) throws DbException, FormatException; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java index 32659fe4f..4eaa98114 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java @@ -94,9 +94,6 @@ abstract class MessageParserImpl m.getGroupId(), shareable, message, m.getTimestamp()); } - protected abstract S createShareable(BdfList descriptor) - throws FormatException; - @Override public AcceptMessage parseAcceptMessage(Message m, BdfList body) throws FormatException { 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 0a672f578..f5f2eda20 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 @@ -113,13 +113,7 @@ abstract class ProtocolEngineImpl private Message sendInviteMessage(Transaction txn, Session s, @Nullable String message, long timestamp) throws DbException { - Group g = db.getGroup(txn, s.getShareableId()); - BdfList descriptor; - try { - descriptor = clientHelper.toList(g.getDescriptor()); - } catch (FormatException e) { - throw new DbException(e); // Invalid group descriptor - } + BdfList descriptor = getDescriptor(txn, s.getShareableId()); long localTimestamp = Math.max(timestamp, getLocalTimestamp(s)); Message m = messageEncoder.encodeInviteMessage(s.getContactGroupId(), localTimestamp, s.getLastLocalMessageId(), descriptor, message); @@ -373,7 +367,8 @@ abstract class ProtocolEngineImpl m.getTimestamp(), false); // Broadcast an event ContactId contactId = getContactId(txn, m.getContactGroupId()); - txn.attach(getInvitationResponseReceivedEvent(m, contactId)); + S shareable = getShareable(txn, s.getShareableId()); + txn.attach(getInvitationResponseReceivedEvent(m, contactId, shareable)); // Move to the next state return new Session(nextState, s.getContactGroupId(), s.getShareableId(), s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(), @@ -391,7 +386,7 @@ abstract class ProtocolEngineImpl } abstract Event getInvitationResponseReceivedEvent(AcceptMessage m, - ContactId contactId); + ContactId contactId, S shareable); @Override public Session onDeclineMessage(Transaction txn, Session s, @@ -431,7 +426,8 @@ abstract class ProtocolEngineImpl } // Broadcast an event ContactId contactId = getContactId(txn, m.getContactGroupId()); - txn.attach(getInvitationResponseReceivedEvent(m, contactId)); + S shareable = getShareable(txn, s.getShareableId()); + txn.attach(getInvitationResponseReceivedEvent(m, contactId, shareable)); // Move to the next state return new Session(START, s.getContactGroupId(), s.getShareableId(), s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(), @@ -439,7 +435,7 @@ abstract class ProtocolEngineImpl } abstract Event getInvitationResponseReceivedEvent(DeclineMessage m, - ContactId contactId); + ContactId contactId, S shareable); @Override public Session onLeaveMessage(Transaction txn, Session s, @@ -530,6 +526,26 @@ abstract class ProtocolEngineImpl sent.getId(), null, 0, 0); } + private S getShareable(Transaction txn, GroupId groupId) + throws DbException { + BdfList descriptor = getDescriptor(txn, groupId); + try { + return messageParser.createShareable(descriptor); + } catch (FormatException e) { + throw new DbException(e); + } + } + + private BdfList getDescriptor(Transaction txn, GroupId groupId) + throws DbException { + Group g = db.getGroup(txn, groupId); + try { + return clientHelper.toList(g.getDescriptor()); + } catch (FormatException e) { + throw new DbException(e); // Invalid group descriptor + } + } + private void markInvitesUnavailableToAnswer(Transaction txn, Session s) throws DbException, FormatException { GroupId shareableId = s.getShareableId(); 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 de529ddf3..8b9af66db 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 @@ -28,7 +28,7 @@ import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateRequest; -import org.briarproject.briar.api.sharing.InvitationResponse; +import org.briarproject.briar.api.messaging.PrivateResponse; import org.briarproject.briar.api.sharing.Shareable; import org.briarproject.briar.api.sharing.SharingInvitationItem; import org.briarproject.briar.api.sharing.SharingManager; @@ -345,23 +345,35 @@ abstract class SharingManagerImpl .getMessageMetadataAsDictionary(txn, contactGroupId, query); List messages = new ArrayList<>(results.size()); + // get invite messages first and remember shareables + Map shareables = new HashMap<>(); for (Entry e : results.entrySet()) { MessageId m = e.getKey(); MessageMetadata meta = messageParser.parseMetadata(e.getValue()); - MessageStatus status = db.getMessageStatus(txn, c, m); MessageType type = meta.getMessageType(); - if (type == INVITE) { - messages.add( - parseInvitationRequest(txn, c, m, meta, status)); - } else if (type == ACCEPT) { - messages.add( - parseInvitationResponse(contactGroupId, m, meta, - status, true)); + if (type != INVITE) continue; + MessageStatus status = db.getMessageStatus(txn, c, m); + PrivateRequest invite = parseInvitationRequest(txn, c, m, + meta, status); + messages.add(invite); + shareables.put(invite.getObject().getId(), invite.getObject()); + } + for (Entry e : results.entrySet()) { + MessageId m = e.getKey(); + MessageMetadata meta = + messageParser.parseMetadata(e.getValue()); + MessageType type = meta.getMessageType(); + if (type == INVITE) continue; + MessageStatus status = db.getMessageStatus(txn, c, m); + S shareable = shareables.get(meta.getShareableId()); + if (shareable == null) throw new AssertionError(); + if (type == ACCEPT) { + messages.add(parseInvitationResponse(contactGroupId, m, + meta, status, shareable, true)); } else if (type == DECLINE) { - messages.add( - parseInvitationResponse(contactGroupId, m, meta, - status, false)); + messages.add(parseInvitationResponse(contactGroupId, m, + meta, status, shareable, false)); } } return messages; @@ -370,7 +382,7 @@ abstract class SharingManagerImpl } } - private PrivateRequest parseInvitationRequest(Transaction txn, + private PrivateRequest parseInvitationRequest(Transaction txn, ContactId c, MessageId m, MessageMetadata meta, MessageStatus status) throws DbException, FormatException { // Look up the invite message to get the details of the private group @@ -384,13 +396,12 @@ abstract class SharingManagerImpl meta.isAvailableToAnswer(), canBeOpened); } - private InvitationResponse parseInvitationResponse(GroupId contactGroupId, + private PrivateResponse parseInvitationResponse(GroupId contactGroupId, MessageId m, MessageMetadata meta, MessageStatus status, - boolean accept) { + S shareable, boolean accept) { return invitationFactory.createInvitationResponse(m, contactGroupId, meta.getTimestamp(), meta.isLocal(), status.isSent(), - status.isSeen(), meta.isRead(), meta.getShareableId(), - accept); + status.isSeen(), meta.isRead(), shareable, accept); } @Override diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java index 867a1ea47..c7dfdcb8f 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java @@ -159,7 +159,7 @@ public class IntroductionIntegrationTest eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response1Received); assertEquals(introducee2.getAuthor().getName(), - listener0.getResponse().getName()); + listener0.getResponse().getObject().getName()); assertGroupCount(messageTracker0, g1.getId(), 2, 1); // sync second ACCEPT message @@ -167,7 +167,7 @@ public class IntroductionIntegrationTest eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response2Received); assertEquals(introducee1.getAuthor().getName(), - listener0.getResponse().getName()); + listener0.getResponse().getObject().getName()); assertGroupCount(messageTracker0, g2.getId(), 2, 1); // sync forwarded ACCEPT messages to introducees @@ -265,7 +265,7 @@ public class IntroductionIntegrationTest // assert that the name on the decline event is correct assertEquals(introducee2.getAuthor().getName(), - listener0.getResponse().getName()); + listener0.getResponse().getObject().getName()); // sync second response sync2To0(1, true); @@ -282,7 +282,7 @@ public class IntroductionIntegrationTest // assert that the name on the decline event is correct eventWaiter.await(TIMEOUT, 1); assertEquals(introducee1.getAuthor().getName(), - listener2.getResponse().getName()); + listener2.getResponse().getObject().getName()); // note how the introducer does not forward the second response, // because after the first decline the protocol finished @@ -351,7 +351,7 @@ public class IntroductionIntegrationTest // assert that the name on the decline event is correct eventWaiter.await(TIMEOUT, 1); assertEquals(contact2From0.getAuthor().getName(), - listener1.getResponse().getName()); + listener1.getResponse().getObject().getName()); assertFalse(contactManager1 .contactExists(author2.getId(), author1.getId())); @@ -475,7 +475,7 @@ public class IntroductionIntegrationTest // assert that the name on the decline event is correct eventWaiter.await(TIMEOUT, 1); assertEquals(introducee1.getAuthor().getName(), - listener2.getResponse().getName()); + listener2.getResponse().getObject().getName()); // assert that introducee2 is in correct state introduceeSession = getIntroduceeSession(c2); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java index 19e996e43..1fb0100d3 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java @@ -310,6 +310,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { oneOf(messageTracker) .trackMessage(txn, contactGroupId, inviteTimestamp + 1, false); + oneOf(privateGroupManager).getPrivateGroup(txn, privateGroupId); + will(returnValue(privateGroup)); }}); expectGetContactId(); expectSetPrivateGroupVisibility(SHARED); @@ -399,6 +401,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { oneOf(messageTracker) .trackMessage(txn, contactGroupId, inviteTimestamp + 1, false); + oneOf(privateGroupManager).getPrivateGroup(txn, privateGroupId); + will(returnValue(privateGroup)); }}); expectGetContactId(); CreatorSession newSession = diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java index 67d34d580..0d55b34f6 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java @@ -2,6 +2,7 @@ package org.briarproject.briar.privategroup.invitation; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.sync.Group; +import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.test.TestDatabaseModule; import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.messaging.PrivateMessageHeader; @@ -12,7 +13,6 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse; -import org.briarproject.briar.api.sharing.InvitationResponse; import org.briarproject.briar.test.BriarIntegrationTest; import org.briarproject.briar.test.BriarIntegrationTestComponent; import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent; @@ -124,7 +124,8 @@ public class GroupInvitationIntegrationTest for (PrivateMessageHeader m : messages) { if (m instanceof GroupInvitationResponse) { foundResponse = true; - InvitationResponse response = (GroupInvitationResponse) m; + GroupInvitationResponse response = (GroupInvitationResponse) m; + assertEquals(privateGroup0, response.getObject()); assertTrue(response.isLocal()); assertFalse(response.wasAccepted()); } @@ -140,7 +141,8 @@ public class GroupInvitationIntegrationTest for (PrivateMessageHeader m : messages) { if (m instanceof GroupInvitationResponse) { foundResponse = true; - InvitationResponse response = (GroupInvitationResponse) m; + GroupInvitationResponse response = (GroupInvitationResponse) m; + assertEquals(privateGroup0, response.getObject()); assertFalse(response.isLocal()); assertFalse(response.wasAccepted()); } @@ -171,24 +173,27 @@ public class GroupInvitationIntegrationTest for (PrivateMessageHeader m : messages) { if (m instanceof GroupInvitationResponse) { foundResponse = true; - InvitationResponse response = (GroupInvitationResponse) m; + GroupInvitationResponse response = (GroupInvitationResponse) m; + assertEquals(privateGroup0, response.getObject()); assertTrue(response.wasAccepted()); } else { - assertTrue(((GroupInvitationRequest) m).doesExist()); + GroupInvitationRequest request = (GroupInvitationRequest) m; + assertEquals(privateGroup0, request.getObject()); + assertTrue(request.doesExist()); } } assertTrue(foundResponse); sync1To0(1, true); - messages = - groupInvitationManager0.getMessages(contactId1From0); + messages = groupInvitationManager0.getMessages(contactId1From0); assertEquals(2, messages.size()); foundResponse = false; for (PrivateMessageHeader m : messages) { if (m instanceof GroupInvitationResponse) { foundResponse = true; - InvitationResponse response = (GroupInvitationResponse) m; + GroupInvitationResponse response = (GroupInvitationResponse) m; + assertEquals(privateGroup0, response.getObject()); assertTrue(response.wasAccepted()); } } @@ -432,6 +437,36 @@ public class GroupInvitationIntegrationTest sync1To0(1, true); } + @Test(expected = AssertionError.class) + public void testDeleteOnlyInvitationFails() throws Exception { + // send invitation + sendInvitation(clock.currentTimeMillis(), null); + sync0To1(1, true); + + // save MessageId of invitation + Collection messages = + groupInvitationManager1.getMessages(contactId0From1); + assertEquals(1, messages.size()); + MessageId inviteId = messages.iterator().next().getId(); + + // decline invitation + groupInvitationManager1 + .respondToInvitation(contactId0From1, privateGroup0, false); + + // we should have an invitation and a decline message + messages = groupInvitationManager1.getMessages(contactId0From1); + assertEquals(2, messages.size()); + + // delete only invitation + withinTransaction(db1, txn -> { + db1.deleteMessage(txn, inviteId); + db1.deleteMessageMetadata(txn, inviteId); + }); + + // This should fail + groupInvitationManager1.getMessages(contactId0From1); + } + private void sendInvitation(long timestamp, @Nullable String msg) throws DbException { byte[] signature = groupInvitationFactory.signInvitation(contact1From0, diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java index 7d5df8dde..197785228 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java @@ -682,6 +682,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { contactGroup.getId(), query); will(returnValue(results)); // first message + oneOf(messageParser).parseMetadata(meta2); + will(returnValue(messageMetadata2)); oneOf(messageParser).parseMetadata(meta); will(returnValue(messageMetadata1)); oneOf(db).getMessageStatus(txn, contactId, message.getId()); @@ -695,6 +697,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { // second message oneOf(messageParser).parseMetadata(meta2); will(returnValue(messageMetadata2)); + oneOf(messageParser).parseMetadata(meta); + will(returnValue(messageMetadata1)); oneOf(db).getMessageStatus(txn, contactId, messageId2); // end transaction oneOf(db).commitTransaction(txn); @@ -709,9 +713,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { if (m.getId().equals(message.getId())) { assertTrue(m instanceof GroupInvitationRequest); assertEquals(time1, m.getTimestamp()); + assertEquals(pg, ((GroupInvitationRequest) m).getObject()); } else if (m.getId().equals(messageId2)) { assertTrue(m instanceof GroupInvitationResponse); assertEquals(time2, m.getTimestamp()); + assertEquals(pg, ((GroupInvitationResponse) m).getObject()); } else { throw new AssertionError(); } diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java index 11e52c033..6663c6d86 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java @@ -154,6 +154,7 @@ public class BlogSharingIntegrationTest for (PrivateMessageHeader m : list) { if (m instanceof BlogInvitationRequest) { BlogInvitationRequest invitation = (BlogInvitationRequest) m; + assertEquals(blog2, invitation.getObject()); assertFalse(invitation.wasAnswered()); assertEquals(blog2.getAuthor().getName(), invitation.getName()); @@ -161,6 +162,7 @@ public class BlogSharingIntegrationTest assertEquals("Hi!", invitation.getMessage()); } else { BlogInvitationResponse response = (BlogInvitationResponse) m; + assertEquals(blog2, response.getObject()); assertTrue(response.wasAccepted()); assertTrue(response.isLocal()); } @@ -225,6 +227,7 @@ public class BlogSharingIntegrationTest for (PrivateMessageHeader m : list) { if (m instanceof BlogInvitationRequest) { BlogInvitationRequest invitation = (BlogInvitationRequest) m; + assertEquals(rssBlog, invitation.getObject()); assertFalse(invitation.wasAnswered()); assertEquals(rssBlog.getAuthor().getName(), invitation.getName()); @@ -232,6 +235,7 @@ public class BlogSharingIntegrationTest assertEquals("Hi!", invitation.getMessage()); } else { BlogInvitationResponse response = (BlogInvitationResponse) m; + assertEquals(rssBlog, response.getObject()); assertTrue(response.wasAccepted()); assertTrue(response.isLocal()); } @@ -284,12 +288,14 @@ public class BlogSharingIntegrationTest for (PrivateMessageHeader m : list) { if (m instanceof BlogInvitationRequest) { BlogInvitationRequest invitation = (BlogInvitationRequest) m; + assertEquals(blog2, invitation.getObject()); assertFalse(invitation.wasAnswered()); assertEquals(blog2.getAuthor().getName(), invitation.getName()); assertEquals(null, invitation.getMessage()); } else { BlogInvitationResponse response = (BlogInvitationResponse) m; + assertEquals(blog2, response.getObject()); assertFalse(response.wasAccepted()); assertTrue(response.isLocal()); } @@ -612,7 +618,7 @@ public class BlogSharingIntegrationTest } } - private void listenToEvents(boolean accept) throws DbException { + private void listenToEvents(boolean accept) { listener0 = new SharerListener(); c0.getEventBus().addListener(listener0); listener1 = new InviteeListener(accept); diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java index c5fba4522..46db59820 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java @@ -137,15 +137,15 @@ public class ForumSharingIntegrationTest // check other things are alright with the forum message for (PrivateMessageHeader m : list) { if (m instanceof ForumInvitationRequest) { - ForumInvitationRequest invitation = - (ForumInvitationRequest) m; + ForumInvitationRequest invitation = (ForumInvitationRequest) m; assertFalse(invitation.wasAnswered()); assertEquals(forum0.getName(), invitation.getName()); + assertEquals(forum0, invitation.getObject()); assertEquals("Hi!", invitation.getMessage()); assertTrue(invitation.doesExist()); } else { - ForumInvitationResponse response = - (ForumInvitationResponse) m; + ForumInvitationResponse response = (ForumInvitationResponse) m; + assertEquals(forum0, response.getObject()); assertTrue(response.wasAccepted()); assertTrue(response.isLocal()); } @@ -195,12 +195,14 @@ public class ForumSharingIntegrationTest for (PrivateMessageHeader m : list) { if (m instanceof ForumInvitationRequest) { ForumInvitationRequest invitation = (ForumInvitationRequest) m; + assertEquals(forum0, invitation.getObject()); assertFalse(invitation.wasAnswered()); assertEquals(forum0.getName(), invitation.getName()); assertEquals(null, invitation.getMessage()); assertFalse(invitation.doesExist()); } else { ForumInvitationResponse response = (ForumInvitationResponse) m; + assertEquals(forum0, response.getObject()); assertFalse(response.wasAccepted()); assertTrue(response.isLocal()); } 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 f10d94183..ab934de94 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 @@ -10,6 +10,7 @@ import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.identity.AuthorFactory; @@ -376,4 +377,21 @@ public abstract class BriarIntegrationTest