Unify all private message responses in one PrivateResponse class

This also adds `Shareable`s to invitation response
which is a precondition for #561
This commit is contained in:
Torsten Grote
2018-09-05 15:22:12 -03:00
parent ffeca8817f
commit 61e18f104e
37 changed files with 357 additions and 307 deletions

View File

@@ -25,7 +25,7 @@ import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent; import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent; 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 org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
import java.util.ArrayList; import java.util.ArrayList;
@@ -107,8 +107,8 @@ class BlogControllerImpl extends BaseControllerImpl
} else if (e instanceof BlogInvitationResponseReceivedEvent) { } else if (e instanceof BlogInvitationResponseReceivedEvent) {
BlogInvitationResponseReceivedEvent b = BlogInvitationResponseReceivedEvent b =
(BlogInvitationResponseReceivedEvent) e; (BlogInvitationResponseReceivedEvent) e;
InvitationResponse r = b.getResponse(); PrivateResponse<Blog> r = b.getResponse();
if (r.getShareableId().equals(groupId) && r.wasAccepted()) { if (r.getObject().getId().equals(groupId) && r.wasAccepted()) {
LOG.info("Blog invitation accepted"); LOG.info("Blog invitation accepted");
onBlogInvitationAccepted(b.getContactId()); onBlogInvitationAccepted(b.getContactId());
} }

View File

@@ -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.ConversationManager;
import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.PrivateRequest; 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.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.InvitationRequestReceivedEvent;
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; 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"); LOG.info("Invitation response received, updating item");
InvitationResponseReceivedEvent m = InvitationResponseReceivedEvent m =
(InvitationResponseReceivedEvent) e; (InvitationResponseReceivedEvent) e;
InvitationResponse ir = m.getResponse(); PrivateResponse ir = m.getResponse();
updateItem(m.getContactId(), ir); updateItem(m.getContactId(), ir);
} }
} }

View File

@@ -71,9 +71,9 @@ import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory; import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.PrivateRequest; 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.messaging.event.PrivateMessageReceivedEvent;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; 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.InvitationRequestReceivedEvent;
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
import org.thoughtcrime.securesms.components.util.FutureTaskListener; import org.thoughtcrime.securesms.components.util.FutureTaskListener;
@@ -424,7 +424,7 @@ public class ConversationActivity extends BriarActivity
item = ConversationItem item = ConversationItem
.from(this, contactName, (PrivateRequest) i); .from(this, contactName, (PrivateRequest) i);
} else { } else {
InvitationResponse r = (InvitationResponse) i; PrivateResponse r = (PrivateResponse) i;
item = ConversationItem.from(this, contactName, r); item = ConversationItem.from(this, contactName, r);
} }
items.add(item); items.add(item);
@@ -507,16 +507,16 @@ public class ConversationActivity extends BriarActivity
(IntroductionRequestReceivedEvent) e; (IntroductionRequestReceivedEvent) e;
if (event.getContactId().equals(contactId)) { if (event.getContactId().equals(contactId)) {
LOG.info("Introduction request received, adding..."); LOG.info("Introduction request received, adding...");
IntroductionRequest ir = event.getIntroductionRequest(); PrivateRequest ir = event.getIntroductionRequest();
handleIntroductionRequest(ir); handlePrivateRequest(ir);
} }
} else if (e instanceof IntroductionResponseReceivedEvent) { } else if (e instanceof IntroductionResponseReceivedEvent) {
IntroductionResponseReceivedEvent event = IntroductionResponseReceivedEvent event =
(IntroductionResponseReceivedEvent) e; (IntroductionResponseReceivedEvent) e;
if (event.getContactId().equals(contactId)) { if (event.getContactId().equals(contactId)) {
LOG.info("Introduction response received, adding..."); LOG.info("Introduction response received, adding...");
IntroductionResponse ir = event.getIntroductionResponse(); PrivateResponse ir = event.getIntroductionResponse();
handleIntroductionResponse(ir); handlePrivateResponse(ir);
} }
} else if (e instanceof InvitationRequestReceivedEvent) { } else if (e instanceof InvitationRequestReceivedEvent) {
InvitationRequestReceivedEvent event = InvitationRequestReceivedEvent event =
@@ -524,15 +524,15 @@ public class ConversationActivity extends BriarActivity
if (event.getContactId().equals(contactId)) { if (event.getContactId().equals(contactId)) {
LOG.info("Invitation received, adding..."); LOG.info("Invitation received, adding...");
PrivateRequest ir = event.getRequest(); PrivateRequest ir = event.getRequest();
handleInvitationRequest(ir); handlePrivateRequest(ir);
} }
} else if (e instanceof InvitationResponseReceivedEvent) { } else if (e instanceof InvitationResponseReceivedEvent) {
InvitationResponseReceivedEvent event = InvitationResponseReceivedEvent event =
(InvitationResponseReceivedEvent) e; (InvitationResponseReceivedEvent) e;
if (event.getContactId().equals(contactId)) { if (event.getContactId().equals(contactId)) {
LOG.info("Invitation response received, adding..."); LOG.info("Invitation response received, adding...");
InvitationResponse ir = event.getResponse(); PrivateResponse ir = event.getResponse();
handleInvitationResponse(ir); 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<String>() { getContactNameTask().addListener(new FutureTaskListener<String>() {
@Override @Override
public void onSuccess(String contactName) { 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<String>() { getContactNameTask().addListener(new FutureTaskListener<String>() {
@Override @Override
public void onSuccess(String contactName) { public void onSuccess(String contactName) {
@@ -584,46 +584,8 @@ public class ConversationActivity extends BriarActivity
}); });
} }
private void handleInvitationRequest(PrivateRequest m) { private void markMessages(Collection<MessageId> messageIds, boolean sent,
getContactNameTask().addListener(new FutureTaskListener<String>() { boolean seen) {
@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<String>() {
@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<MessageId> messageIds,
boolean sent, boolean seen) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
adapter.incrementRevision(); adapter.incrementRevision();
Set<MessageId> messages = new HashSet<>(messageIds); Set<MessageId> messages = new HashSet<>(messageIds);

View File

@@ -17,9 +17,9 @@ import org.briarproject.briar.api.introduction.IntroductionRequest;
import org.briarproject.briar.api.introduction.IntroductionResponse; import org.briarproject.briar.api.introduction.IntroductionResponse;
import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.PrivateRequest; 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.GroupInvitationRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
import org.briarproject.briar.api.sharing.InvitationResponse;
import org.briarproject.briar.api.sharing.Shareable; import org.briarproject.briar.api.sharing.Shareable;
import javax.annotation.Nullable; 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, static ConversationItem from(Context ctx, String contactName,
PrivateRequest ir) { PrivateRequest ir) {
if (ir.isLocal()) { if (ir.isLocal()) {
@@ -196,7 +156,44 @@ abstract class ConversationItem {
} }
static ConversationItem from(Context ctx, String contactName, 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; @StringRes int res;
if (ir.isLocal()) { if (ir.isLocal()) {
if (ir.wasAccepted()) { if (ir.wasAccepted()) {
@@ -208,7 +205,7 @@ abstract class ConversationItem {
res = R.string.groups_invitations_response_accepted_sent; res = R.string.groups_invitations_response_accepted_sent;
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unknown InvitationResponse"); "Unknown PrivateResponse");
} }
} else { } else {
if (ir instanceof ForumInvitationResponse) { if (ir instanceof ForumInvitationResponse) {
@@ -219,7 +216,7 @@ abstract class ConversationItem {
res = R.string.groups_invitations_response_declined_sent; res = R.string.groups_invitations_response_declined_sent;
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unknown InvitationResponse"); "Unknown PrivateResponse");
} }
} }
String text = ctx.getString(res, contactName); String text = ctx.getString(res, contactName);
@@ -235,7 +232,7 @@ abstract class ConversationItem {
res = R.string.groups_invitations_response_accepted_received; res = R.string.groups_invitations_response_accepted_received;
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unknown InvitationResponse"); "Unknown PrivateResponse");
} }
} else { } else {
if (ir instanceof ForumInvitationResponse) { if (ir instanceof ForumInvitationResponse) {
@@ -246,7 +243,7 @@ abstract class ConversationItem {
res = R.string.groups_invitations_response_declined_received; res = R.string.groups_invitations_response_declined_received;
} else { } else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unknown InvitationResponse"); "Unknown PrivateResponse");
} }
} }
String text = ctx.getString(res, contactName); String text = ctx.getString(res, contactName);
@@ -261,14 +258,12 @@ abstract class ConversationItem {
* PrivateMessageHeader. * PrivateMessageHeader.
**/ **/
static ConversationItem from(Context ctx, PrivateMessageHeader h) { static ConversationItem from(Context ctx, PrivateMessageHeader h) {
if(h instanceof IntroductionRequest) { if(h instanceof IntroductionResponse) {
return from(ctx, "", (IntroductionRequest) h);
} else if(h instanceof IntroductionResponse) {
return from(ctx, "", (IntroductionResponse) h); return from(ctx, "", (IntroductionResponse) h);
} else if(h instanceof PrivateRequest) { } else if(h instanceof PrivateRequest) {
return from(ctx, "", (PrivateRequest) h); return from(ctx, "", (PrivateRequest) h);
} else if(h instanceof InvitationResponse) { } else if(h instanceof PrivateResponse) {
return from(ctx, "", (InvitationResponse) h); return from(ctx, "", (PrivateResponse) h);
} else { } else {
return from(h); return from(h);
} }

View File

@@ -86,7 +86,7 @@ class ForumControllerImpl extends
(ForumInvitationResponseReceivedEvent) e; (ForumInvitationResponseReceivedEvent) e;
ForumInvitationResponse r = ForumInvitationResponse r =
(ForumInvitationResponse) f.getResponse(); (ForumInvitationResponse) f.getResponse();
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) { if (r.getObject().getId().equals(getGroupId()) && r.wasAccepted()) {
LOG.info("Forum invitation was accepted"); LOG.info("Forum invitation was accepted");
onForumInvitationAccepted(f.getContactId()); onForumInvitationAccepted(f.getContactId());
} }

View File

@@ -101,7 +101,7 @@ class GroupControllerImpl extends
(GroupInvitationResponseReceivedEvent) e; (GroupInvitationResponseReceivedEvent) e;
GroupInvitationResponse r = GroupInvitationResponse r =
(GroupInvitationResponse) g.getResponse(); (GroupInvitationResponse) g.getResponse();
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) { if (getGroupId().equals(r.getObject().getId()) && r.wasAccepted()) {
listener.runOnUiThreadUnlessDestroyed( listener.runOnUiThreadUnlessDestroyed(
() -> listener.onInvitationAccepted(g.getContactId())); () -> listener.onInvitationAccepted(g.getContactId()));
} }

View File

@@ -4,15 +4,15 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.sharing.InvitationResponse; import org.briarproject.briar.api.messaging.PrivateResponse;
@NotNullByDefault @NotNullByDefault
public class BlogInvitationResponse extends InvitationResponse { public class BlogInvitationResponse extends PrivateResponse<Blog> {
public BlogInvitationResponse(MessageId id, GroupId groupId, long time, public BlogInvitationResponse(MessageId id, GroupId groupId, long time,
boolean local, boolean sent, boolean seen, boolean read, boolean local, boolean sent, boolean seen, boolean read,
SessionId sessionId, GroupId blogId, boolean accept) { SessionId sessionId, Blog blog, boolean accept) {
super(id, groupId, time, local, sent, seen, read, sessionId, blogId, super(id, groupId, time, local, sent, seen, read, sessionId, blog,
accept); accept);
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.api.blog.event;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; 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.blog.BlogInvitationResponse;
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent; import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
@@ -10,7 +11,7 @@ import javax.annotation.concurrent.Immutable;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class BlogInvitationResponseReceivedEvent public class BlogInvitationResponseReceivedEvent
extends InvitationResponseReceivedEvent { extends InvitationResponseReceivedEvent<Blog> {
public BlogInvitationResponseReceivedEvent(ContactId contactId, public BlogInvitationResponseReceivedEvent(ContactId contactId,
BlogInvitationResponse response) { BlogInvitationResponse response) {

View File

@@ -4,18 +4,18 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.SessionId; 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; import javax.annotation.concurrent.Immutable;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class ForumInvitationResponse extends InvitationResponse { public class ForumInvitationResponse extends PrivateResponse<Forum> {
public ForumInvitationResponse(MessageId id, GroupId groupId, long time, public ForumInvitationResponse(MessageId id, GroupId groupId, long time,
boolean local, boolean sent, boolean seen, boolean read, boolean local, boolean sent, boolean seen, boolean read,
SessionId sessionId, GroupId forumId, boolean accept) { SessionId sessionId, Forum forum, boolean accept) {
super(id, groupId, time, local, sent, seen, read, sessionId, forumId, super(id, groupId, time, local, sent, seen, read, sessionId, forum,
accept); accept);
} }

View File

@@ -4,45 +4,19 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.SessionId; 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 javax.annotation.concurrent.Immutable;
import static org.briarproject.briar.api.introduction.Role.INTRODUCER;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class IntroductionResponse extends PrivateMessageHeader { public class IntroductionResponse extends PrivateResponse<Introduction> {
private final SessionId sessionId; public IntroductionResponse(MessageId messageId, GroupId groupId, long time,
private final String name; boolean local, boolean sent, boolean seen, boolean read,
private final Role role; SessionId sessionId, Introduction introduction, boolean accepted) {
private final boolean accepted; super(messageId, groupId, time, local, sent, seen, read, sessionId,
introduction, 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;
} }
} }

View File

@@ -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<O extends Nameable>
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;
}
}

View File

@@ -2,7 +2,8 @@ package org.briarproject.briar.api.privategroup.event;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; 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 org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
@@ -10,10 +11,10 @@ import javax.annotation.concurrent.Immutable;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class GroupInvitationResponseReceivedEvent public class GroupInvitationResponseReceivedEvent
extends InvitationResponseReceivedEvent { extends InvitationResponseReceivedEvent<PrivateGroup> {
public GroupInvitationResponseReceivedEvent(ContactId contactId, public GroupInvitationResponseReceivedEvent(ContactId contactId,
InvitationResponse response) { PrivateResponse<PrivateGroup> response) {
super(contactId, response); super(contactId, response);
} }
} }

View File

@@ -4,19 +4,20 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.SessionId; 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; import javax.annotation.concurrent.Immutable;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class GroupInvitationResponse extends InvitationResponse { public class GroupInvitationResponse extends PrivateResponse<PrivateGroup> {
public GroupInvitationResponse(MessageId id, GroupId groupId, long time, public GroupInvitationResponse(MessageId id, GroupId groupId, long time,
boolean local, boolean sent, boolean seen, boolean read, 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, super(id, groupId, time, local, sent, seen, read, sessionId,
shareableId, accept); privateGroup, accept);
} }
} }

View File

@@ -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;
}
}

View File

@@ -3,19 +3,21 @@ package org.briarproject.briar.api.sharing.event;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; 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; import javax.annotation.concurrent.Immutable;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public abstract class InvitationResponseReceivedEvent extends Event { public abstract class InvitationResponseReceivedEvent<S extends Shareable>
extends Event {
private final ContactId contactId; private final ContactId contactId;
private final InvitationResponse response; private final PrivateResponse<S> response;
public InvitationResponseReceivedEvent(ContactId contactId, public InvitationResponseReceivedEvent(ContactId contactId,
InvitationResponse response) { PrivateResponse<S> response) {
this.contactId = contactId; this.contactId = contactId;
this.response = response; this.response = response;
} }
@@ -24,7 +26,7 @@ public abstract class InvitationResponseReceivedEvent extends Event {
return contactId; return contactId;
} }
public InvitationResponse getResponse() { public PrivateResponse<S> getResponse() {
return response; return response;
} }
} }

View File

@@ -20,6 +20,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId; 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.IntroductionResponse;
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent; import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
@@ -147,12 +148,13 @@ abstract class AbstractProtocolEngine<S extends Session>
void broadcastIntroductionResponseReceivedEvent(Transaction txn, Session s, void broadcastIntroductionResponseReceivedEvent(Transaction txn, Session s,
AuthorId sender, Author otherAuthor, AbstractIntroductionMessage m) AuthorId sender, Author otherAuthor, AbstractIntroductionMessage m)
throws DbException { throws DbException {
Introduction introduction = new Introduction(otherAuthor, s.getRole());
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId(); AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
Contact c = contactManager.getContact(txn, sender, localAuthorId); Contact c = contactManager.getContact(txn, sender, localAuthorId);
IntroductionResponse response = IntroductionResponse response =
new IntroductionResponse(s.getSessionId(), m.getMessageId(), new IntroductionResponse(m.getMessageId(), m.getGroupId(),
m.getGroupId(), s.getRole(), m.getTimestamp(), false, m.getTimestamp(), false, false, false, false,
false, false, false, otherAuthor.getName(), s.getSessionId(), introduction,
m instanceof AcceptMessage); m instanceof AcceptMessage);
IntroductionResponseReceivedEvent e = IntroductionResponseReceivedEvent e =
new IntroductionResponseReceivedEvent(c.getId(), response); new IntroductionResponseReceivedEvent(c.getId(), response);

View File

@@ -509,9 +509,10 @@ class IntroductionManagerImpl extends ConversationClientImpl
sessionId = session.getSessionId(); sessionId = session.getSessionId();
author = session.getRemote().author; author = session.getRemote().author;
} else throw new AssertionError(); } else throw new AssertionError();
return new IntroductionResponse(sessionId, m, contactGroupId, Introduction introduction = new Introduction(author, role);
role, meta.getTimestamp(), meta.isLocal(), status.isSent(), return new IntroductionResponse(m, contactGroupId, meta.getTimestamp(),
status.isSeen(), meta.isRead(), author.getName(), accept); meta.isLocal(), status.isSent(), status.isSeen(), meta.isRead(),
sessionId, introduction, accept);
} }
private void removeSessionWithIntroducer(Transaction txn, private void removeSessionWithIntroducer(Transaction txn,

View File

@@ -15,6 +15,7 @@ import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.ProtocolStateException;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.privategroup.GroupMessageFactory; 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.PrivateGroupFactory;
import org.briarproject.briar.api.privategroup.PrivateGroupManager; import org.briarproject.briar.api.privategroup.PrivateGroupManager;
import org.briarproject.briar.api.privategroup.event.GroupInvitationResponseReceivedEvent; import org.briarproject.briar.api.privategroup.event.GroupInvitationResponseReceivedEvent;
@@ -193,8 +194,10 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
setPrivateGroupVisibility(txn, s, SHARED); setPrivateGroupVisibility(txn, s, SHARED);
// Broadcast an event // Broadcast an event
ContactId contactId = getContactId(txn, m.getContactGroupId()); ContactId contactId = getContactId(txn, m.getContactGroupId());
PrivateGroup privateGroup =
privateGroupManager.getPrivateGroup(txn, m.getPrivateGroupId());
txn.attach(new GroupInvitationResponseReceivedEvent(contactId, txn.attach(new GroupInvitationResponseReceivedEvent(contactId,
createInvitationResponse(m, contactId, true))); createInvitationResponse(m, privateGroup, true)));
// Move to the JOINED state // Move to the JOINED state
return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(), return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(),
sent.getId(), m.getId(), sent.getTimestamp(), sent.getId(), m.getId(), sent.getTimestamp(),
@@ -215,8 +218,10 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
m.getTimestamp(), false); m.getTimestamp(), false);
// Broadcast an event // Broadcast an event
ContactId contactId = getContactId(txn, m.getContactGroupId()); ContactId contactId = getContactId(txn, m.getContactGroupId());
PrivateGroup privateGroup =
privateGroupManager.getPrivateGroup(txn, m.getPrivateGroupId());
txn.attach(new GroupInvitationResponseReceivedEvent(contactId, txn.attach(new GroupInvitationResponseReceivedEvent(contactId,
createInvitationResponse(m, contactId, false))); createInvitationResponse(m, privateGroup, false)));
// Move to the START state // Move to the START state
return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(), return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(),
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(), s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
@@ -254,10 +259,11 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
} }
private GroupInvitationResponse createInvitationResponse( private GroupInvitationResponse createInvitationResponse(
GroupInvitationMessage m, ContactId c, boolean accept) { GroupInvitationMessage m, PrivateGroup privateGroup,
boolean accept) {
SessionId sessionId = new SessionId(m.getPrivateGroupId().getBytes()); SessionId sessionId = new SessionId(m.getPrivateGroupId().getBytes());
return new GroupInvitationResponse(m.getId(), m.getContactGroupId(), return new GroupInvitationResponse(m.getId(), m.getContactGroupId(),
m.getTimestamp(), false, false, true, false, sessionId, m.getTimestamp(), false, false, true, false, sessionId,
m.getPrivateGroupId(), accept); privateGroup, accept);
} }
} }

View File

@@ -353,7 +353,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
private <S extends Session> S handleAction(Transaction txn, private <S extends Session> S handleAction(Transaction txn,
LocalAction type, S session, ProtocolEngine<S> engine) LocalAction type, S session, ProtocolEngine<S> engine)
throws DbException, FormatException { throws DbException {
if (type == LocalAction.INVITE) { if (type == LocalAction.INVITE) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} else if (type == LocalAction.JOIN) { } else if (type == LocalAction.JOIN) {
@@ -392,23 +392,36 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
.getMessageMetadataAsDictionary(txn, contactGroupId, query); .getMessageMetadataAsDictionary(txn, contactGroupId, query);
List<PrivateMessageHeader> messages = List<PrivateMessageHeader> messages =
new ArrayList<>(results.size()); new ArrayList<>(results.size());
// get invite message first and remember private groups
Map<SessionId, PrivateGroup> privateGroups = new HashMap<>();
for (Entry<MessageId, BdfDictionary> e : results.entrySet()) { for (Entry<MessageId, BdfDictionary> e : results.entrySet()) {
MessageId m = e.getKey(); MessageId m = e.getKey();
MessageMetadata meta = MessageMetadata meta =
messageParser.parseMetadata(e.getValue()); messageParser.parseMetadata(e.getValue());
MessageStatus status = db.getMessageStatus(txn, c, m);
MessageType type = meta.getMessageType(); MessageType type = meta.getMessageType();
if (type == INVITE) { if (type != INVITE) continue;
messages.add(parseInvitationRequest(txn, c, contactGroupId, MessageStatus status = db.getMessageStatus(txn, c, m);
m, meta, status)); GroupInvitationRequest invite = parseInvitationRequest(txn,
} else if (type == JOIN) { contactGroupId, m, meta, status);
messages.add( messages.add(invite);
parseInvitationResponse(c, contactGroupId, m, meta, privateGroups.put(invite.getSessionId(), invite.getObject());
status, true)); }
for (Entry<MessageId, BdfDictionary> 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) { } else if (type == LEAVE) {
messages.add( messages.add(parseInvitationResponse(contactGroupId, m,
parseInvitationResponse(c, contactGroupId, m, meta, meta, status, sessionId, privateGroup, false));
status, false));
} }
} }
return messages; return messages;
@@ -418,9 +431,8 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
} }
private GroupInvitationRequest parseInvitationRequest(Transaction txn, private GroupInvitationRequest parseInvitationRequest(Transaction txn,
ContactId c, GroupId contactGroupId, MessageId m, GroupId contactGroupId, MessageId m, MessageMetadata meta,
MessageMetadata meta, MessageStatus status) MessageStatus status) throws DbException, FormatException {
throws DbException, FormatException {
SessionId sessionId = getSessionId(meta.getPrivateGroupId()); SessionId sessionId = getSessionId(meta.getPrivateGroupId());
// Look up the invite message to get the details of the private group // Look up the invite message to get the details of the private group
InviteMessage invite = messageParser.getInviteMessage(txn, m); InviteMessage invite = messageParser.getInviteMessage(txn, m);
@@ -436,15 +448,14 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
invite.getMessage(), meta.isAvailableToAnswer(), canBeOpened); invite.getMessage(), meta.isAvailableToAnswer(), canBeOpened);
} }
private GroupInvitationResponse parseInvitationResponse(ContactId c, private GroupInvitationResponse parseInvitationResponse(
GroupId contactGroupId, MessageId m, MessageMetadata meta, GroupId contactGroupId, MessageId m, MessageMetadata meta,
MessageStatus status, boolean accept) MessageStatus status, SessionId sessionId,
throws DbException, FormatException { PrivateGroup privateGroup, boolean accept) {
SessionId sessionId = getSessionId(meta.getPrivateGroupId());
return new GroupInvitationResponse(m, contactGroupId, return new GroupInvitationResponse(m, contactGroupId,
meta.getTimestamp(), meta.isLocal(), status.isSent(), meta.getTimestamp(), meta.isLocal(), status.isSent(),
status.isSeen(), meta.isRead(), sessionId, status.isSeen(), meta.isRead(), sessionId, privateGroup,
meta.getPrivateGroupId(), accept); accept);
} }
@Override @Override

View File

@@ -30,10 +30,10 @@ public class BlogInvitationFactoryImpl
@Override @Override
public BlogInvitationResponse createInvitationResponse(MessageId id, public BlogInvitationResponse createInvitationResponse(MessageId id,
GroupId contactGroupId, long time, boolean local, boolean sent, GroupId contactGroupId, long time, boolean local, boolean sent,
boolean seen, boolean read, GroupId shareableId, boolean accept) { boolean seen, boolean read, Blog blog, boolean accept) {
SessionId sessionId = new SessionId(shareableId.getBytes()); SessionId sessionId = new SessionId(blog.getId().getBytes());
return new BlogInvitationResponse(id, contactGroupId, time, local, return new BlogInvitationResponse(id, contactGroupId, time, local, sent,
sent, seen, read, sessionId, shareableId, accept); seen, read, sessionId, blog, accept);
} }
} }

View File

@@ -30,7 +30,7 @@ class BlogMessageParserImpl extends MessageParserImpl<Blog> {
} }
@Override @Override
protected Blog createShareable(BdfList descriptor) throws FormatException { public Blog createShareable(BdfList descriptor) throws FormatException {
// Author, RSS // Author, RSS
BdfList authorList = descriptor.getList(0); BdfList authorList = descriptor.getList(0);
boolean rssFeed = descriptor.getBoolean(1); boolean rssFeed = descriptor.getBoolean(1);

View File

@@ -59,21 +59,21 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl<Blog> {
@Override @Override
Event getInvitationResponseReceivedEvent(AcceptMessage m, Event getInvitationResponseReceivedEvent(AcceptMessage m,
ContactId contactId) { ContactId contactId, Blog shareable) {
BlogInvitationResponse response = invitationFactory BlogInvitationResponse response = invitationFactory
.createInvitationResponse(m.getId(), m.getContactGroupId(), .createInvitationResponse(m.getId(), m.getContactGroupId(),
m.getTimestamp(), false, false, true, false, m.getTimestamp(), false, false, true, false,
m.getShareableId(), true); shareable, true);
return new BlogInvitationResponseReceivedEvent(contactId, response); return new BlogInvitationResponseReceivedEvent(contactId, response);
} }
@Override @Override
Event getInvitationResponseReceivedEvent(DeclineMessage m, Event getInvitationResponseReceivedEvent(DeclineMessage m,
ContactId contactId) { ContactId contactId, Blog shareable) {
BlogInvitationResponse response = invitationFactory BlogInvitationResponse response = invitationFactory
.createInvitationResponse(m.getId(), m.getContactGroupId(), .createInvitationResponse(m.getId(), m.getContactGroupId(),
m.getTimestamp(), false, false, true, false, m.getTimestamp(), false, false, true, false,
m.getShareableId(), true); shareable, true);
return new BlogInvitationResponseReceivedEvent(contactId, response); return new BlogInvitationResponseReceivedEvent(contactId, response);
} }

View File

@@ -30,11 +30,10 @@ public class ForumInvitationFactoryImpl
@Override @Override
public ForumInvitationResponse createInvitationResponse(MessageId id, public ForumInvitationResponse createInvitationResponse(MessageId id,
GroupId contactGroupId, long time, boolean local, boolean sent, GroupId contactGroupId, long time, boolean local, boolean sent,
boolean seen, boolean read, GroupId shareableId, boolean seen, boolean read, Forum forum, boolean accept) {
boolean accept) { SessionId sessionId = new SessionId(forum.getId().getBytes());
SessionId sessionId = new SessionId(shareableId.getBytes());
return new ForumInvitationResponse(id, contactGroupId, time, local, return new ForumInvitationResponse(id, contactGroupId, time, local,
sent, seen, read, sessionId, shareableId, accept); sent, seen, read, sessionId, forum, accept);
} }
} }

View File

@@ -24,7 +24,7 @@ class ForumMessageParserImpl extends MessageParserImpl<Forum> {
} }
@Override @Override
protected Forum createShareable(BdfList descriptor) throws FormatException { public Forum createShareable(BdfList descriptor) throws FormatException {
// Name, salt // Name, salt
String name = descriptor.getString(0); String name = descriptor.getString(0);
byte[] salt = descriptor.getRaw(1); byte[] salt = descriptor.getRaw(1);

View File

@@ -61,21 +61,21 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl<Forum> {
@Override @Override
Event getInvitationResponseReceivedEvent(AcceptMessage m, Event getInvitationResponseReceivedEvent(AcceptMessage m,
ContactId contactId) { ContactId contactId, Forum shareable) {
ForumInvitationResponse response = invitationFactory ForumInvitationResponse response = invitationFactory
.createInvitationResponse(m.getId(), m.getContactGroupId(), .createInvitationResponse(m.getId(), m.getContactGroupId(),
m.getTimestamp(), false, false, true, false, m.getTimestamp(), false, false, true, false,
m.getShareableId(), true); shareable, true);
return new ForumInvitationResponseReceivedEvent(contactId, response); return new ForumInvitationResponseReceivedEvent(contactId, response);
} }
@Override @Override
Event getInvitationResponseReceivedEvent(DeclineMessage m, Event getInvitationResponseReceivedEvent(DeclineMessage m,
ContactId contactId) { ContactId contactId, Forum shareable) {
ForumInvitationResponse response = invitationFactory ForumInvitationResponse response = invitationFactory
.createInvitationResponse(m.getId(), m.getContactGroupId(), .createInvitationResponse(m.getId(), m.getContactGroupId(),
m.getTimestamp(), false, false, true, false, m.getTimestamp(), false, false, true, false,
m.getShareableId(), true); shareable, true);
return new ForumInvitationResponseReceivedEvent(contactId, response); return new ForumInvitationResponseReceivedEvent(contactId, response);
} }

View File

@@ -4,10 +4,10 @@ import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.messaging.PrivateRequest; 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.Shareable;
public interface InvitationFactory<S extends Shareable, I extends InvitationResponse> { public interface InvitationFactory<S extends Shareable, I extends PrivateResponse<S>> {
PrivateRequest<S> createInvitationRequest(boolean local, boolean sent, PrivateRequest<S> createInvitationRequest(boolean local, boolean sent,
boolean seen, boolean read, InviteMessage<S> m, ContactId c, boolean seen, boolean read, InviteMessage<S> m, ContactId c,
@@ -15,7 +15,6 @@ public interface InvitationFactory<S extends Shareable, I extends InvitationResp
I createInvitationResponse(MessageId id, I createInvitationResponse(MessageId id,
GroupId contactGroupId, long time, boolean local, boolean sent, GroupId contactGroupId, long time, boolean local, boolean sent,
boolean seen, boolean read, GroupId shareableId, boolean seen, boolean read, S shareable, boolean accept);
boolean accept);
} }

View File

@@ -22,6 +22,8 @@ interface MessageParser<S extends Shareable> {
MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException; MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException;
S createShareable(BdfList descriptor) throws FormatException;
InviteMessage<S> getInviteMessage(Transaction txn, MessageId m) InviteMessage<S> getInviteMessage(Transaction txn, MessageId m)
throws DbException, FormatException; throws DbException, FormatException;

View File

@@ -94,9 +94,6 @@ abstract class MessageParserImpl<S extends Shareable>
m.getGroupId(), shareable, message, m.getTimestamp()); m.getGroupId(), shareable, message, m.getTimestamp());
} }
protected abstract S createShareable(BdfList descriptor)
throws FormatException;
@Override @Override
public AcceptMessage parseAcceptMessage(Message m, BdfList body) public AcceptMessage parseAcceptMessage(Message m, BdfList body)
throws FormatException { throws FormatException {

View File

@@ -113,13 +113,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
private Message sendInviteMessage(Transaction txn, Session s, private Message sendInviteMessage(Transaction txn, Session s,
@Nullable String message, long timestamp) throws DbException { @Nullable String message, long timestamp) throws DbException {
Group g = db.getGroup(txn, s.getShareableId()); BdfList descriptor = getDescriptor(txn, s.getShareableId());
BdfList descriptor;
try {
descriptor = clientHelper.toList(g.getDescriptor());
} catch (FormatException e) {
throw new DbException(e); // Invalid group descriptor
}
long localTimestamp = Math.max(timestamp, getLocalTimestamp(s)); long localTimestamp = Math.max(timestamp, getLocalTimestamp(s));
Message m = messageEncoder.encodeInviteMessage(s.getContactGroupId(), Message m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
localTimestamp, s.getLastLocalMessageId(), descriptor, message); localTimestamp, s.getLastLocalMessageId(), descriptor, message);
@@ -373,7 +367,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
m.getTimestamp(), false); m.getTimestamp(), false);
// Broadcast an event // Broadcast an event
ContactId contactId = getContactId(txn, m.getContactGroupId()); 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 // Move to the next state
return new Session(nextState, s.getContactGroupId(), s.getShareableId(), return new Session(nextState, s.getContactGroupId(), s.getShareableId(),
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(), s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
@@ -391,7 +386,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
} }
abstract Event getInvitationResponseReceivedEvent(AcceptMessage m, abstract Event getInvitationResponseReceivedEvent(AcceptMessage m,
ContactId contactId); ContactId contactId, S shareable);
@Override @Override
public Session onDeclineMessage(Transaction txn, Session s, public Session onDeclineMessage(Transaction txn, Session s,
@@ -431,7 +426,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
} }
// Broadcast an event // Broadcast an event
ContactId contactId = getContactId(txn, m.getContactGroupId()); 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 // Move to the next state
return new Session(START, s.getContactGroupId(), s.getShareableId(), return new Session(START, s.getContactGroupId(), s.getShareableId(),
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(), s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
@@ -439,7 +435,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
} }
abstract Event getInvitationResponseReceivedEvent(DeclineMessage m, abstract Event getInvitationResponseReceivedEvent(DeclineMessage m,
ContactId contactId); ContactId contactId, S shareable);
@Override @Override
public Session onLeaveMessage(Transaction txn, Session s, public Session onLeaveMessage(Transaction txn, Session s,
@@ -530,6 +526,26 @@ abstract class ProtocolEngineImpl<S extends Shareable>
sent.getId(), null, 0, 0); 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) private void markInvitesUnavailableToAnswer(Transaction txn, Session s)
throws DbException, FormatException { throws DbException, FormatException {
GroupId shareableId = s.getShareableId(); GroupId shareableId = s.getShareableId();

View File

@@ -28,7 +28,7 @@ import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.PrivateRequest; 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.Shareable;
import org.briarproject.briar.api.sharing.SharingInvitationItem; import org.briarproject.briar.api.sharing.SharingInvitationItem;
import org.briarproject.briar.api.sharing.SharingManager; import org.briarproject.briar.api.sharing.SharingManager;
@@ -345,23 +345,35 @@ abstract class SharingManagerImpl<S extends Shareable>
.getMessageMetadataAsDictionary(txn, contactGroupId, query); .getMessageMetadataAsDictionary(txn, contactGroupId, query);
List<PrivateMessageHeader> messages = List<PrivateMessageHeader> messages =
new ArrayList<>(results.size()); new ArrayList<>(results.size());
// get invite messages first and remember shareables
Map<GroupId, S> shareables = new HashMap<>();
for (Entry<MessageId, BdfDictionary> e : results.entrySet()) { for (Entry<MessageId, BdfDictionary> e : results.entrySet()) {
MessageId m = e.getKey(); MessageId m = e.getKey();
MessageMetadata meta = MessageMetadata meta =
messageParser.parseMetadata(e.getValue()); messageParser.parseMetadata(e.getValue());
MessageStatus status = db.getMessageStatus(txn, c, m);
MessageType type = meta.getMessageType(); MessageType type = meta.getMessageType();
if (type == INVITE) { if (type != INVITE) continue;
messages.add( MessageStatus status = db.getMessageStatus(txn, c, m);
parseInvitationRequest(txn, c, m, meta, status)); PrivateRequest<S> invite = parseInvitationRequest(txn, c, m,
} else if (type == ACCEPT) { meta, status);
messages.add( messages.add(invite);
parseInvitationResponse(contactGroupId, m, meta, shareables.put(invite.getObject().getId(), invite.getObject());
status, true)); }
for (Entry<MessageId, BdfDictionary> 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) { } else if (type == DECLINE) {
messages.add( messages.add(parseInvitationResponse(contactGroupId, m,
parseInvitationResponse(contactGroupId, m, meta, meta, status, shareable, false));
status, false));
} }
} }
return messages; return messages;
@@ -370,7 +382,7 @@ abstract class SharingManagerImpl<S extends Shareable>
} }
} }
private PrivateRequest parseInvitationRequest(Transaction txn, private PrivateRequest<S> parseInvitationRequest(Transaction txn,
ContactId c, MessageId m, MessageMetadata meta, ContactId c, MessageId m, MessageMetadata meta,
MessageStatus status) throws DbException, FormatException { MessageStatus status) throws DbException, FormatException {
// Look up the invite message to get the details of the private group // Look up the invite message to get the details of the private group
@@ -384,13 +396,12 @@ abstract class SharingManagerImpl<S extends Shareable>
meta.isAvailableToAnswer(), canBeOpened); meta.isAvailableToAnswer(), canBeOpened);
} }
private InvitationResponse parseInvitationResponse(GroupId contactGroupId, private PrivateResponse<S> parseInvitationResponse(GroupId contactGroupId,
MessageId m, MessageMetadata meta, MessageStatus status, MessageId m, MessageMetadata meta, MessageStatus status,
boolean accept) { S shareable, boolean accept) {
return invitationFactory.createInvitationResponse(m, contactGroupId, return invitationFactory.createInvitationResponse(m, contactGroupId,
meta.getTimestamp(), meta.isLocal(), status.isSent(), meta.getTimestamp(), meta.isLocal(), status.isSent(),
status.isSeen(), meta.isRead(), meta.getShareableId(), status.isSeen(), meta.isRead(), shareable, accept);
accept);
} }
@Override @Override

View File

@@ -159,7 +159,7 @@ public class IntroductionIntegrationTest
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response1Received); assertTrue(listener0.response1Received);
assertEquals(introducee2.getAuthor().getName(), assertEquals(introducee2.getAuthor().getName(),
listener0.getResponse().getName()); listener0.getResponse().getObject().getName());
assertGroupCount(messageTracker0, g1.getId(), 2, 1); assertGroupCount(messageTracker0, g1.getId(), 2, 1);
// sync second ACCEPT message // sync second ACCEPT message
@@ -167,7 +167,7 @@ public class IntroductionIntegrationTest
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response2Received); assertTrue(listener0.response2Received);
assertEquals(introducee1.getAuthor().getName(), assertEquals(introducee1.getAuthor().getName(),
listener0.getResponse().getName()); listener0.getResponse().getObject().getName());
assertGroupCount(messageTracker0, g2.getId(), 2, 1); assertGroupCount(messageTracker0, g2.getId(), 2, 1);
// sync forwarded ACCEPT messages to introducees // sync forwarded ACCEPT messages to introducees
@@ -265,7 +265,7 @@ public class IntroductionIntegrationTest
// assert that the name on the decline event is correct // assert that the name on the decline event is correct
assertEquals(introducee2.getAuthor().getName(), assertEquals(introducee2.getAuthor().getName(),
listener0.getResponse().getName()); listener0.getResponse().getObject().getName());
// sync second response // sync second response
sync2To0(1, true); sync2To0(1, true);
@@ -282,7 +282,7 @@ public class IntroductionIntegrationTest
// assert that the name on the decline event is correct // assert that the name on the decline event is correct
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertEquals(introducee1.getAuthor().getName(), assertEquals(introducee1.getAuthor().getName(),
listener2.getResponse().getName()); listener2.getResponse().getObject().getName());
// note how the introducer does not forward the second response, // note how the introducer does not forward the second response,
// because after the first decline the protocol finished // 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 // assert that the name on the decline event is correct
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertEquals(contact2From0.getAuthor().getName(), assertEquals(contact2From0.getAuthor().getName(),
listener1.getResponse().getName()); listener1.getResponse().getObject().getName());
assertFalse(contactManager1 assertFalse(contactManager1
.contactExists(author2.getId(), author1.getId())); .contactExists(author2.getId(), author1.getId()));
@@ -475,7 +475,7 @@ public class IntroductionIntegrationTest
// assert that the name on the decline event is correct // assert that the name on the decline event is correct
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertEquals(introducee1.getAuthor().getName(), assertEquals(introducee1.getAuthor().getName(),
listener2.getResponse().getName()); listener2.getResponse().getObject().getName());
// assert that introducee2 is in correct state // assert that introducee2 is in correct state
introduceeSession = getIntroduceeSession(c2); introduceeSession = getIntroduceeSession(c2);

View File

@@ -310,6 +310,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
oneOf(messageTracker) oneOf(messageTracker)
.trackMessage(txn, contactGroupId, inviteTimestamp + 1, .trackMessage(txn, contactGroupId, inviteTimestamp + 1,
false); false);
oneOf(privateGroupManager).getPrivateGroup(txn, privateGroupId);
will(returnValue(privateGroup));
}}); }});
expectGetContactId(); expectGetContactId();
expectSetPrivateGroupVisibility(SHARED); expectSetPrivateGroupVisibility(SHARED);
@@ -399,6 +401,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
oneOf(messageTracker) oneOf(messageTracker)
.trackMessage(txn, contactGroupId, inviteTimestamp + 1, .trackMessage(txn, contactGroupId, inviteTimestamp + 1,
false); false);
oneOf(privateGroupManager).getPrivateGroup(txn, privateGroupId);
will(returnValue(privateGroup));
}}); }});
expectGetContactId(); expectGetContactId();
CreatorSession newSession = CreatorSession newSession =

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule; import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.ProtocolStateException;
import org.briarproject.briar.api.messaging.PrivateMessageHeader; 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.GroupInvitationManager;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse; 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.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent; import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent; import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
@@ -124,7 +124,8 @@ public class GroupInvitationIntegrationTest
for (PrivateMessageHeader m : messages) { for (PrivateMessageHeader m : messages) {
if (m instanceof GroupInvitationResponse) { if (m instanceof GroupInvitationResponse) {
foundResponse = true; foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m; GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(privateGroup0, response.getObject());
assertTrue(response.isLocal()); assertTrue(response.isLocal());
assertFalse(response.wasAccepted()); assertFalse(response.wasAccepted());
} }
@@ -140,7 +141,8 @@ public class GroupInvitationIntegrationTest
for (PrivateMessageHeader m : messages) { for (PrivateMessageHeader m : messages) {
if (m instanceof GroupInvitationResponse) { if (m instanceof GroupInvitationResponse) {
foundResponse = true; foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m; GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(privateGroup0, response.getObject());
assertFalse(response.isLocal()); assertFalse(response.isLocal());
assertFalse(response.wasAccepted()); assertFalse(response.wasAccepted());
} }
@@ -171,24 +173,27 @@ public class GroupInvitationIntegrationTest
for (PrivateMessageHeader m : messages) { for (PrivateMessageHeader m : messages) {
if (m instanceof GroupInvitationResponse) { if (m instanceof GroupInvitationResponse) {
foundResponse = true; foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m; GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(privateGroup0, response.getObject());
assertTrue(response.wasAccepted()); assertTrue(response.wasAccepted());
} else { } else {
assertTrue(((GroupInvitationRequest) m).doesExist()); GroupInvitationRequest request = (GroupInvitationRequest) m;
assertEquals(privateGroup0, request.getObject());
assertTrue(request.doesExist());
} }
} }
assertTrue(foundResponse); assertTrue(foundResponse);
sync1To0(1, true); sync1To0(1, true);
messages = messages = groupInvitationManager0.getMessages(contactId1From0);
groupInvitationManager0.getMessages(contactId1From0);
assertEquals(2, messages.size()); assertEquals(2, messages.size());
foundResponse = false; foundResponse = false;
for (PrivateMessageHeader m : messages) { for (PrivateMessageHeader m : messages) {
if (m instanceof GroupInvitationResponse) { if (m instanceof GroupInvitationResponse) {
foundResponse = true; foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m; GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(privateGroup0, response.getObject());
assertTrue(response.wasAccepted()); assertTrue(response.wasAccepted());
} }
} }
@@ -432,6 +437,36 @@ public class GroupInvitationIntegrationTest
sync1To0(1, true); 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<PrivateMessageHeader> 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 private void sendInvitation(long timestamp, @Nullable String msg) throws
DbException { DbException {
byte[] signature = groupInvitationFactory.signInvitation(contact1From0, byte[] signature = groupInvitationFactory.signInvitation(contact1From0,

View File

@@ -682,6 +682,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
contactGroup.getId(), query); contactGroup.getId(), query);
will(returnValue(results)); will(returnValue(results));
// first message // first message
oneOf(messageParser).parseMetadata(meta2);
will(returnValue(messageMetadata2));
oneOf(messageParser).parseMetadata(meta); oneOf(messageParser).parseMetadata(meta);
will(returnValue(messageMetadata1)); will(returnValue(messageMetadata1));
oneOf(db).getMessageStatus(txn, contactId, message.getId()); oneOf(db).getMessageStatus(txn, contactId, message.getId());
@@ -695,6 +697,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
// second message // second message
oneOf(messageParser).parseMetadata(meta2); oneOf(messageParser).parseMetadata(meta2);
will(returnValue(messageMetadata2)); will(returnValue(messageMetadata2));
oneOf(messageParser).parseMetadata(meta);
will(returnValue(messageMetadata1));
oneOf(db).getMessageStatus(txn, contactId, messageId2); oneOf(db).getMessageStatus(txn, contactId, messageId2);
// end transaction // end transaction
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
@@ -709,9 +713,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
if (m.getId().equals(message.getId())) { if (m.getId().equals(message.getId())) {
assertTrue(m instanceof GroupInvitationRequest); assertTrue(m instanceof GroupInvitationRequest);
assertEquals(time1, m.getTimestamp()); assertEquals(time1, m.getTimestamp());
assertEquals(pg, ((GroupInvitationRequest) m).getObject());
} else if (m.getId().equals(messageId2)) { } else if (m.getId().equals(messageId2)) {
assertTrue(m instanceof GroupInvitationResponse); assertTrue(m instanceof GroupInvitationResponse);
assertEquals(time2, m.getTimestamp()); assertEquals(time2, m.getTimestamp());
assertEquals(pg, ((GroupInvitationResponse) m).getObject());
} else { } else {
throw new AssertionError(); throw new AssertionError();
} }

View File

@@ -154,6 +154,7 @@ public class BlogSharingIntegrationTest
for (PrivateMessageHeader m : list) { for (PrivateMessageHeader m : list) {
if (m instanceof BlogInvitationRequest) { if (m instanceof BlogInvitationRequest) {
BlogInvitationRequest invitation = (BlogInvitationRequest) m; BlogInvitationRequest invitation = (BlogInvitationRequest) m;
assertEquals(blog2, invitation.getObject());
assertFalse(invitation.wasAnswered()); assertFalse(invitation.wasAnswered());
assertEquals(blog2.getAuthor().getName(), assertEquals(blog2.getAuthor().getName(),
invitation.getName()); invitation.getName());
@@ -161,6 +162,7 @@ public class BlogSharingIntegrationTest
assertEquals("Hi!", invitation.getMessage()); assertEquals("Hi!", invitation.getMessage());
} else { } else {
BlogInvitationResponse response = (BlogInvitationResponse) m; BlogInvitationResponse response = (BlogInvitationResponse) m;
assertEquals(blog2, response.getObject());
assertTrue(response.wasAccepted()); assertTrue(response.wasAccepted());
assertTrue(response.isLocal()); assertTrue(response.isLocal());
} }
@@ -225,6 +227,7 @@ public class BlogSharingIntegrationTest
for (PrivateMessageHeader m : list) { for (PrivateMessageHeader m : list) {
if (m instanceof BlogInvitationRequest) { if (m instanceof BlogInvitationRequest) {
BlogInvitationRequest invitation = (BlogInvitationRequest) m; BlogInvitationRequest invitation = (BlogInvitationRequest) m;
assertEquals(rssBlog, invitation.getObject());
assertFalse(invitation.wasAnswered()); assertFalse(invitation.wasAnswered());
assertEquals(rssBlog.getAuthor().getName(), assertEquals(rssBlog.getAuthor().getName(),
invitation.getName()); invitation.getName());
@@ -232,6 +235,7 @@ public class BlogSharingIntegrationTest
assertEquals("Hi!", invitation.getMessage()); assertEquals("Hi!", invitation.getMessage());
} else { } else {
BlogInvitationResponse response = (BlogInvitationResponse) m; BlogInvitationResponse response = (BlogInvitationResponse) m;
assertEquals(rssBlog, response.getObject());
assertTrue(response.wasAccepted()); assertTrue(response.wasAccepted());
assertTrue(response.isLocal()); assertTrue(response.isLocal());
} }
@@ -284,12 +288,14 @@ public class BlogSharingIntegrationTest
for (PrivateMessageHeader m : list) { for (PrivateMessageHeader m : list) {
if (m instanceof BlogInvitationRequest) { if (m instanceof BlogInvitationRequest) {
BlogInvitationRequest invitation = (BlogInvitationRequest) m; BlogInvitationRequest invitation = (BlogInvitationRequest) m;
assertEquals(blog2, invitation.getObject());
assertFalse(invitation.wasAnswered()); assertFalse(invitation.wasAnswered());
assertEquals(blog2.getAuthor().getName(), assertEquals(blog2.getAuthor().getName(),
invitation.getName()); invitation.getName());
assertEquals(null, invitation.getMessage()); assertEquals(null, invitation.getMessage());
} else { } else {
BlogInvitationResponse response = (BlogInvitationResponse) m; BlogInvitationResponse response = (BlogInvitationResponse) m;
assertEquals(blog2, response.getObject());
assertFalse(response.wasAccepted()); assertFalse(response.wasAccepted());
assertTrue(response.isLocal()); 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(); listener0 = new SharerListener();
c0.getEventBus().addListener(listener0); c0.getEventBus().addListener(listener0);
listener1 = new InviteeListener(accept); listener1 = new InviteeListener(accept);

View File

@@ -137,15 +137,15 @@ public class ForumSharingIntegrationTest
// check other things are alright with the forum message // check other things are alright with the forum message
for (PrivateMessageHeader m : list) { for (PrivateMessageHeader m : list) {
if (m instanceof ForumInvitationRequest) { if (m instanceof ForumInvitationRequest) {
ForumInvitationRequest invitation = ForumInvitationRequest invitation = (ForumInvitationRequest) m;
(ForumInvitationRequest) m;
assertFalse(invitation.wasAnswered()); assertFalse(invitation.wasAnswered());
assertEquals(forum0.getName(), invitation.getName()); assertEquals(forum0.getName(), invitation.getName());
assertEquals(forum0, invitation.getObject());
assertEquals("Hi!", invitation.getMessage()); assertEquals("Hi!", invitation.getMessage());
assertTrue(invitation.doesExist()); assertTrue(invitation.doesExist());
} else { } else {
ForumInvitationResponse response = ForumInvitationResponse response = (ForumInvitationResponse) m;
(ForumInvitationResponse) m; assertEquals(forum0, response.getObject());
assertTrue(response.wasAccepted()); assertTrue(response.wasAccepted());
assertTrue(response.isLocal()); assertTrue(response.isLocal());
} }
@@ -195,12 +195,14 @@ public class ForumSharingIntegrationTest
for (PrivateMessageHeader m : list) { for (PrivateMessageHeader m : list) {
if (m instanceof ForumInvitationRequest) { if (m instanceof ForumInvitationRequest) {
ForumInvitationRequest invitation = (ForumInvitationRequest) m; ForumInvitationRequest invitation = (ForumInvitationRequest) m;
assertEquals(forum0, invitation.getObject());
assertFalse(invitation.wasAnswered()); assertFalse(invitation.wasAnswered());
assertEquals(forum0.getName(), invitation.getName()); assertEquals(forum0.getName(), invitation.getName());
assertEquals(null, invitation.getMessage()); assertEquals(null, invitation.getMessage());
assertFalse(invitation.doesExist()); assertFalse(invitation.doesExist());
} else { } else {
ForumInvitationResponse response = (ForumInvitationResponse) m; ForumInvitationResponse response = (ForumInvitationResponse) m;
assertEquals(forum0, response.getObject());
assertFalse(response.wasAccepted()); assertFalse(response.wasAccepted());
assertTrue(response.isLocal()); assertTrue(response.isLocal());
} }

View File

@@ -10,6 +10,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; 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.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
@@ -376,4 +377,21 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
assertNotNull(contactId1From2); assertNotNull(contactId1From2);
contactManager2.removeContact(contactId1From2); contactManager2.removeContact(contactId1From2);
} }
@FunctionalInterface
protected interface TransactionScope {
void execute(Transaction txn) throws DbException;
}
protected void withinTransaction(DatabaseComponent db, TransactionScope scope)
throws DbException {
Transaction txn = db.startTransaction(false);
try {
scope.execute(txn);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
}
} }