Store invitation outcome in metadata

and include in canBeOpened calculation for private groups and sharables.
This commit is contained in:
Torsten Grote
2017-01-05 12:56:46 -02:00
parent 5653c6d650
commit 04508a7431
24 changed files with 122 additions and 39 deletions

View File

@@ -174,6 +174,17 @@ abstract class AbstractProtocolEngine<S extends Session>
markMessageAvailableToAnswer(txn, m, false); markMessageAvailableToAnswer(txn, m, false);
} }
void markInviteAccepted(Transaction txn, MessageId m, boolean accepted)
throws DbException {
BdfDictionary meta = new BdfDictionary();
messageEncoder.setInvitationAccepted(meta, accepted);
try {
clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
void subscribeToPrivateGroup(Transaction txn, MessageId inviteId) void subscribeToPrivateGroup(Transaction txn, MessageId inviteId)
throws DbException, FormatException { throws DbException, FormatException {
InviteMessage invite = messageParser.getInviteMessage(txn, inviteId); InviteMessage invite = messageParser.getInviteMessage(txn, inviteId);
@@ -199,8 +210,9 @@ abstract class AbstractProtocolEngine<S extends Session>
private void sendMessage(Transaction txn, Message m, MessageType type, private void sendMessage(Transaction txn, Message m, MessageType type,
GroupId privateGroupId, boolean visibleInConversation) GroupId privateGroupId, boolean visibleInConversation)
throws DbException { throws DbException {
BdfDictionary meta = messageEncoder.encodeMetadata(type, privateGroupId, BdfDictionary meta = messageEncoder
m.getTimestamp(), true, true, visibleInConversation, false); .encodeMetadata(type, privateGroupId, m.getTimestamp(), true,
true, visibleInConversation, false, false);
try { try {
clientHelper.addLocalMessage(txn, m, meta, true); clientHelper.addLocalMessage(txn, m, meta, true);
} catch (FormatException e) { } catch (FormatException e) {

View File

@@ -12,6 +12,7 @@ interface GroupInvitationConstants {
String MSG_KEY_LOCAL = "local"; String MSG_KEY_LOCAL = "local";
String MSG_KEY_VISIBLE_IN_UI = "visibleInUi"; String MSG_KEY_VISIBLE_IN_UI = "visibleInUi";
String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer"; String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer";
String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted";
// Session keys // Session keys
String SESSION_KEY_SESSION_ID = "sessionId"; String SESSION_KEY_SESSION_ID = "sessionId";

View File

@@ -405,7 +405,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
PrivateGroup pg = privateGroupFactory PrivateGroup pg = privateGroupFactory
.createPrivateGroup(invite.getGroupName(), invite.getCreator(), .createPrivateGroup(invite.getGroupName(), invite.getCreator(),
invite.getSalt()); invite.getSalt());
boolean canBeOpened = db.containsGroup(txn, invite.getPrivateGroupId()); // Find out whether the private group can be opened
boolean canBeOpened = meta.wasAccepted() &&
db.containsGroup(txn, invite.getPrivateGroupId());
return new GroupInvitationRequest(m, contactGroupId, return new GroupInvitationRequest(m, contactGroupId,
meta.getTimestamp(), meta.isLocal(), status.isSent(), meta.getTimestamp(), meta.isLocal(), status.isSent(),
status.isSeen(), meta.isRead(), sessionId, pg, c, status.isSeen(), meta.isRead(), sessionId, pg, c,

View File

@@ -112,7 +112,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
// Create the metadata // Create the metadata
BdfDictionary meta = messageEncoder.encodeMetadata(INVITE, BdfDictionary meta = messageEncoder.encodeMetadata(INVITE,
privateGroup.getId(), m.getTimestamp(), false, false, false, privateGroup.getId(), m.getTimestamp(), false, false, false,
false); false, false);
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} }
@@ -125,7 +125,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
checkLength(previousMessageId, UniqueId.LENGTH); checkLength(previousMessageId, UniqueId.LENGTH);
BdfDictionary meta = messageEncoder.encodeMetadata(JOIN, BdfDictionary meta = messageEncoder.encodeMetadata(JOIN,
new GroupId(privateGroupId), m.getTimestamp(), false, false, new GroupId(privateGroupId), m.getTimestamp(), false, false,
false, false); false, false, false);
if (previousMessageId == null) { if (previousMessageId == null) {
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} else { } else {
@@ -144,7 +144,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
checkLength(previousMessageId, UniqueId.LENGTH); checkLength(previousMessageId, UniqueId.LENGTH);
BdfDictionary meta = messageEncoder.encodeMetadata(LEAVE, BdfDictionary meta = messageEncoder.encodeMetadata(LEAVE,
new GroupId(privateGroupId), m.getTimestamp(), false, false, new GroupId(privateGroupId), m.getTimestamp(), false, false,
false, false); false, false, false);
if (previousMessageId == null) { if (previousMessageId == null) {
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} else { } else {
@@ -161,7 +161,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
checkLength(privateGroupId, UniqueId.LENGTH); checkLength(privateGroupId, UniqueId.LENGTH);
BdfDictionary meta = messageEncoder.encodeMetadata(ABORT, BdfDictionary meta = messageEncoder.encodeMetadata(ABORT,
new GroupId(privateGroupId), m.getTimestamp(), false, false, new GroupId(privateGroupId), m.getTimestamp(), false, false,
false, false); false, false, false);
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} }
} }

View File

@@ -172,6 +172,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
MessageId inviteId = s.getLastRemoteMessageId(); MessageId inviteId = s.getLastRemoteMessageId();
if (inviteId == null) throw new IllegalStateException(); if (inviteId == null) throw new IllegalStateException();
markMessageAvailableToAnswer(txn, inviteId, false); markMessageAvailableToAnswer(txn, inviteId, false);
// Record the response
markInviteAccepted(txn, inviteId, true);
// Send a JOIN message // Send a JOIN message
Message sent = sendJoinMessage(txn, s, true); Message sent = sendJoinMessage(txn, s, true);
// Track the message // Track the message

View File

@@ -14,12 +14,14 @@ interface MessageEncoder {
BdfDictionary encodeMetadata(MessageType type, GroupId privateGroupId, BdfDictionary encodeMetadata(MessageType type, GroupId privateGroupId,
long timestamp, boolean local, boolean read, boolean visible, long timestamp, boolean local, boolean read, boolean visible,
boolean available); boolean available, boolean accepted);
void setVisibleInUi(BdfDictionary meta, boolean visible); void setVisibleInUi(BdfDictionary meta, boolean visible);
void setAvailableToAnswer(BdfDictionary meta, boolean available); void setAvailableToAnswer(BdfDictionary meta, boolean available);
void setInvitationAccepted(BdfDictionary meta, boolean accepted);
Message encodeInviteMessage(GroupId contactGroupId, GroupId privateGroupId, Message encodeInviteMessage(GroupId contactGroupId, GroupId privateGroupId,
long timestamp, String groupName, Author creator, byte[] salt, long timestamp, String groupName, Author creator, byte[] salt,
@Nullable String message, byte[] signature); @Nullable String message, byte[] signature);

View File

@@ -17,6 +17,7 @@ import javax.inject.Inject;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID;
@@ -44,7 +45,7 @@ class MessageEncoderImpl implements MessageEncoder {
@Override @Override
public BdfDictionary encodeMetadata(MessageType type, public BdfDictionary encodeMetadata(MessageType type,
GroupId privateGroupId, long timestamp, boolean local, boolean read, GroupId privateGroupId, long timestamp, boolean local, boolean read,
boolean visible, boolean available) { boolean visible, boolean available, boolean accepted) {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue()); meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue());
meta.put(MSG_KEY_PRIVATE_GROUP_ID, privateGroupId); meta.put(MSG_KEY_PRIVATE_GROUP_ID, privateGroupId);
@@ -53,6 +54,7 @@ class MessageEncoderImpl implements MessageEncoder {
meta.put(MSG_KEY_READ, read); meta.put(MSG_KEY_READ, read);
meta.put(MSG_KEY_VISIBLE_IN_UI, visible); meta.put(MSG_KEY_VISIBLE_IN_UI, visible);
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available); meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted);
return meta; return meta;
} }
@@ -66,6 +68,11 @@ class MessageEncoderImpl implements MessageEncoder {
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available); meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
} }
@Override
public void setInvitationAccepted(BdfDictionary meta, boolean accepted) {
meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted);
}
@Override @Override
public Message encodeInviteMessage(GroupId contactGroupId, public Message encodeInviteMessage(GroupId contactGroupId,
GroupId privateGroupId, long timestamp, String groupName, GroupId privateGroupId, long timestamp, String groupName,

View File

@@ -12,11 +12,11 @@ class MessageMetadata {
private final MessageType type; private final MessageType type;
private final GroupId privateGroupId; private final GroupId privateGroupId;
private final long timestamp; private final long timestamp;
private final boolean local, read, visible, available; private final boolean local, read, visible, available, accepted;
MessageMetadata(MessageType type, GroupId privateGroupId, MessageMetadata(MessageType type, GroupId privateGroupId,
long timestamp, boolean local, boolean read, boolean visible, long timestamp, boolean local, boolean read, boolean visible,
boolean available) { boolean available, boolean accepted) {
this.privateGroupId = privateGroupId; this.privateGroupId = privateGroupId;
this.type = type; this.type = type;
this.timestamp = timestamp; this.timestamp = timestamp;
@@ -24,6 +24,7 @@ class MessageMetadata {
this.read = read; this.read = read;
this.visible = visible; this.visible = visible;
this.available = available; this.available = available;
this.accepted = accepted;
} }
MessageType getMessageType() { MessageType getMessageType() {
@@ -53,4 +54,14 @@ class MessageMetadata {
boolean isAvailableToAnswer() { boolean isAvailableToAnswer() {
return available; return available;
} }
/**
* Returns true if the invitation was accepted.
*
* Only applies to messages of type INVITE.
*/
public boolean wasAccepted() {
return accepted;
}
} }

View File

@@ -21,6 +21,7 @@ import javax.inject.Inject;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID;
@@ -79,8 +80,9 @@ class MessageParserImpl implements MessageParser {
boolean read = meta.getBoolean(MSG_KEY_READ, false); boolean read = meta.getBoolean(MSG_KEY_READ, false);
boolean visible = meta.getBoolean(MSG_KEY_VISIBLE_IN_UI, false); boolean visible = meta.getBoolean(MSG_KEY_VISIBLE_IN_UI, false);
boolean available = meta.getBoolean(MSG_KEY_AVAILABLE_TO_ANSWER, false); boolean available = meta.getBoolean(MSG_KEY_AVAILABLE_TO_ANSWER, false);
boolean accepted = meta.getBoolean(MSG_KEY_INVITATION_ACCEPTED, false);
return new MessageMetadata(type, privateGroupId, timestamp, local, read, return new MessageMetadata(type, privateGroupId, timestamp, local, read,
visible, available); visible, available, accepted);
} }
@Override @Override

View File

@@ -14,12 +14,14 @@ interface MessageEncoder {
BdfDictionary encodeMetadata(MessageType type, GroupId shareableId, BdfDictionary encodeMetadata(MessageType type, GroupId shareableId,
long timestamp, boolean local, boolean read, boolean visible, long timestamp, boolean local, boolean read, boolean visible,
boolean available); boolean available, boolean accepted);
void setVisibleInUi(BdfDictionary meta, boolean visible); void setVisibleInUi(BdfDictionary meta, boolean visible);
void setAvailableToAnswer(BdfDictionary meta, boolean available); void setAvailableToAnswer(BdfDictionary meta, boolean available);
void setInvitationAccepted(BdfDictionary meta, boolean accepted);
Message encodeInviteMessage(GroupId contactGroupId, long timestamp, Message encodeInviteMessage(GroupId contactGroupId, long timestamp,
@Nullable MessageId previousMessageId, BdfList descriptor, @Nullable MessageId previousMessageId, BdfList descriptor,
@Nullable String message); @Nullable String message);

View File

@@ -20,10 +20,11 @@ import static org.briarproject.briar.sharing.MessageType.DECLINE;
import static org.briarproject.briar.sharing.MessageType.INVITE; import static org.briarproject.briar.sharing.MessageType.INVITE;
import static org.briarproject.briar.sharing.MessageType.LEAVE; import static org.briarproject.briar.sharing.MessageType.LEAVE;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_INVITATION_ACCEPTED;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_LOCAL; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_LOCAL;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_MESSAGE_TYPE; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_MESSAGE_TYPE;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_SHAREABLE_ID;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_READ; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_READ;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_SHAREABLE_ID;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_TIMESTAMP; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_TIMESTAMP;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_VISIBLE_IN_UI; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_VISIBLE_IN_UI;
@@ -44,7 +45,7 @@ class MessageEncoderImpl implements MessageEncoder {
@Override @Override
public BdfDictionary encodeMetadata(MessageType type, public BdfDictionary encodeMetadata(MessageType type,
GroupId shareableId, long timestamp, boolean local, boolean read, GroupId shareableId, long timestamp, boolean local, boolean read,
boolean visible, boolean available) { boolean visible, boolean available, boolean accepted) {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue()); meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue());
meta.put(MSG_KEY_SHAREABLE_ID, shareableId); meta.put(MSG_KEY_SHAREABLE_ID, shareableId);
@@ -53,6 +54,7 @@ class MessageEncoderImpl implements MessageEncoder {
meta.put(MSG_KEY_READ, read); meta.put(MSG_KEY_READ, read);
meta.put(MSG_KEY_VISIBLE_IN_UI, visible); meta.put(MSG_KEY_VISIBLE_IN_UI, visible);
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available); meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted);
return meta; return meta;
} }
@@ -66,6 +68,11 @@ class MessageEncoderImpl implements MessageEncoder {
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available); meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
} }
@Override
public void setInvitationAccepted(BdfDictionary meta, boolean accepted) {
meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted);
}
@Override @Override
public Message encodeInviteMessage(GroupId contactGroupId, long timestamp, public Message encodeInviteMessage(GroupId contactGroupId, long timestamp,
@Nullable MessageId previousMessageId, BdfList descriptor, @Nullable MessageId previousMessageId, BdfList descriptor,

View File

@@ -12,10 +12,11 @@ class MessageMetadata {
private final MessageType type; private final MessageType type;
private final GroupId shareableId; private final GroupId shareableId;
private final long timestamp; private final long timestamp;
private final boolean local, read, visible, available; private final boolean local, read, visible, available, accepted;
MessageMetadata(MessageType type, GroupId shareableId, long timestamp, MessageMetadata(MessageType type, GroupId shareableId, long timestamp,
boolean local, boolean read, boolean visible, boolean available) { boolean local, boolean read, boolean visible, boolean available,
boolean accepted) {
this.shareableId = shareableId; this.shareableId = shareableId;
this.type = type; this.type = type;
this.timestamp = timestamp; this.timestamp = timestamp;
@@ -23,6 +24,7 @@ class MessageMetadata {
this.read = read; this.read = read;
this.visible = visible; this.visible = visible;
this.available = available; this.available = available;
this.accepted = accepted;
} }
MessageType getMessageType() { MessageType getMessageType() {
@@ -53,4 +55,13 @@ class MessageMetadata {
return available; return available;
} }
/**
* Returns true if the invitation was accepted.
*
* Only applies to messages of type INVITE.
*/
public boolean wasAccepted() {
return accepted;
}
} }

View File

@@ -20,6 +20,7 @@ import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AVAILABLE_
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_LOCAL; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_LOCAL;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_MESSAGE_TYPE; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_MESSAGE_TYPE;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_READ; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_READ;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_INVITATION_ACCEPTED;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_SHAREABLE_ID; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_SHAREABLE_ID;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_TIMESTAMP; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_TIMESTAMP;
import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_VISIBLE_IN_UI; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_VISIBLE_IN_UI;
@@ -68,8 +69,9 @@ abstract class MessageParserImpl<S extends Shareable>
boolean read = meta.getBoolean(MSG_KEY_READ, false); boolean read = meta.getBoolean(MSG_KEY_READ, false);
boolean visible = meta.getBoolean(MSG_KEY_VISIBLE_IN_UI, false); boolean visible = meta.getBoolean(MSG_KEY_VISIBLE_IN_UI, false);
boolean available = meta.getBoolean(MSG_KEY_AVAILABLE_TO_ANSWER, false); boolean available = meta.getBoolean(MSG_KEY_AVAILABLE_TO_ANSWER, false);
boolean accepted = meta.getBoolean(MSG_KEY_INVITATION_ACCEPTED, false);
return new MessageMetadata(type, shareableId, timestamp, local, read, return new MessageMetadata(type, shareableId, timestamp, local, read,
visible, available); visible, available, accepted);
} }
@Override @Override

View File

@@ -148,6 +148,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
MessageId inviteId = s.getLastRemoteMessageId(); MessageId inviteId = s.getLastRemoteMessageId();
if (inviteId == null) throw new IllegalStateException(); if (inviteId == null) throw new IllegalStateException();
markMessageAvailableToAnswer(txn, inviteId, false); markMessageAvailableToAnswer(txn, inviteId, false);
// Mark the invite message as accepted
markInvitationAccepted(txn, inviteId, true);
// Send a ACCEPT message // Send a ACCEPT message
Message sent = sendAcceptMessage(txn, s); Message sent = sendAcceptMessage(txn, s);
// Track the message // Track the message
@@ -568,8 +570,9 @@ abstract class ProtocolEngineImpl<S extends Shareable>
private void sendMessage(Transaction txn, Message m, MessageType type, private void sendMessage(Transaction txn, Message m, MessageType type,
GroupId shareableId, boolean visibleInConversation) GroupId shareableId, boolean visibleInConversation)
throws DbException { throws DbException {
BdfDictionary meta = messageEncoder.encodeMetadata(type, shareableId, BdfDictionary meta = messageEncoder
m.getTimestamp(), true, true, visibleInConversation, false); .encodeMetadata(type, shareableId, m.getTimestamp(), true, true,
visibleInConversation, false, false);
try { try {
clientHelper.addLocalMessage(txn, m, meta, true); clientHelper.addLocalMessage(txn, m, meta, true);
} catch (FormatException e) { } catch (FormatException e) {
@@ -599,6 +602,17 @@ abstract class ProtocolEngineImpl<S extends Shareable>
} }
} }
private void markInvitationAccepted(Transaction txn, MessageId m,
boolean accepted) throws DbException {
BdfDictionary meta = new BdfDictionary();
messageEncoder.setInvitationAccepted(meta, accepted);
try {
clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
private void setShareableVisibility(Transaction txn, Session session, private void setShareableVisibility(Transaction txn, Session session,
Visibility v) throws DbException, FormatException { Visibility v) throws DbException, FormatException {
ContactId contactId = getContactId(txn, session.getContactGroupId()); ContactId contactId = getContactId(txn, session.getContactGroupId());

View File

@@ -15,6 +15,7 @@ interface SharingConstants {
String MSG_KEY_LOCAL = "local"; String MSG_KEY_LOCAL = "local";
String MSG_KEY_VISIBLE_IN_UI = "visibleInUi"; String MSG_KEY_VISIBLE_IN_UI = "visibleInUi";
String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer"; String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer";
String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted";
// Session keys // Session keys
String SESSION_KEY_STATE = "state"; String SESSION_KEY_STATE = "state";

View File

@@ -319,7 +319,9 @@ abstract class SharingManagerImpl<S extends Shareable>
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
InviteMessage<S> invite = messageParser.getInviteMessage(txn, m); InviteMessage<S> invite = messageParser.getInviteMessage(txn, m);
boolean canBeOpened = db.containsGroup(txn, invite.getShareableId()); // Find out whether the shareable can be opened
boolean canBeOpened = meta.wasAccepted() &&
db.containsGroup(txn, invite.getShareableId());
return invitationFactory return invitationFactory
.createInvitationRequest(meta.isLocal(), status.isSent(), .createInvitationRequest(meta.isLocal(), status.isSent(),
status.isSeen(), meta.isRead(), invite, c, status.isSeen(), meta.isRead(), invite, c,

View File

@@ -65,7 +65,7 @@ abstract class SharingValidator extends BdfMessageValidator {
BdfDictionary meta = messageEncoder BdfDictionary meta = messageEncoder
.encodeMetadata(INVITE, shareableId, m.getTimestamp(), false, .encodeMetadata(INVITE, shareableId, m.getTimestamp(), false,
false, false, false); false, false, false, false);
if (previousMessageId == null) { if (previousMessageId == null) {
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} else { } else {
@@ -88,7 +88,7 @@ abstract class SharingValidator extends BdfMessageValidator {
BdfDictionary meta = messageEncoder BdfDictionary meta = messageEncoder
.encodeMetadata(type, new GroupId(shareableId), .encodeMetadata(type, new GroupId(shareableId),
m.getTimestamp(), false, false, false, false); m.getTimestamp(), false, false, false, false, false);
if (previousMessageId == null) { if (previousMessageId == null) {
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} else { } else {

View File

@@ -169,7 +169,7 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
final boolean visible) throws Exception { final boolean visible) throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder).encodeMetadata(type, privateGroupId, oneOf(messageEncoder).encodeMetadata(type, privateGroupId,
message.getTimestamp(), true, true, visible, false); message.getTimestamp(), true, true, visible, false, false);
will(returnValue(meta)); will(returnValue(meta));
oneOf(clientHelper).addLocalMessage(txn, message, meta, true); oneOf(clientHelper).addLocalMessage(txn, message, meta, true);
}}); }});

View File

@@ -104,6 +104,7 @@ public class GroupInvitationIntegrationTest
assertEquals(privateGroup0.getName(), request.getShareable().getName()); assertEquals(privateGroup0.getName(), request.getShareable().getName());
assertFalse(request.isLocal()); assertFalse(request.isLocal());
assertFalse(request.isRead()); assertFalse(request.isRead());
assertFalse(request.canBeOpened());
} }
@Test @Test
@@ -175,6 +176,8 @@ public class GroupInvitationIntegrationTest
foundResponse = true; foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m; InvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted()); assertTrue(response.wasAccepted());
} else {
assertTrue(((GroupInvitationRequest) m).canBeOpened());
} }
} }
assertTrue(foundResponse); assertTrue(foundResponse);

View File

@@ -638,10 +638,10 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
final long time1 = 1L, time2 = 2L; final long time1 = 1L, time2 = 2L;
final MessageMetadata messageMetadata1 = final MessageMetadata messageMetadata1 =
new MessageMetadata(INVITE, privateGroup.getId(), time1, true, new MessageMetadata(INVITE, privateGroup.getId(), time1, true,
true, true, false); true, true, false, true);
final MessageMetadata messageMetadata2 = final MessageMetadata messageMetadata2 =
new MessageMetadata(JOIN, privateGroup.getId(), time2, true, new MessageMetadata(JOIN, privateGroup.getId(), time2, true,
true, true, true); true, true, true, false);
final InviteMessage invite = final InviteMessage invite =
new InviteMessage(message.getId(), contactGroup.getId(), new InviteMessage(message.getId(), contactGroup.getId(),
privateGroup.getId(), time1, "name", author, privateGroup.getId(), time1, "name", author,

View File

@@ -311,7 +311,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
} else { } else {
oneOf(messageEncoder).encodeMetadata(INVITE, oneOf(messageEncoder).encodeMetadata(INVITE,
message.getGroupId(), message.getTimestamp(), false, message.getGroupId(), message.getTimestamp(), false,
false, false, false); false, false, false, false);
will(returnValue(meta)); will(returnValue(meta));
} }
}}); }});
@@ -389,7 +389,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
BdfList body = BdfList.of(JOIN.getValue(), privateGroup.getId(), null); BdfList body = BdfList.of(JOIN.getValue(), privateGroup.getId(), null);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder).encodeMetadata(JOIN, message.getGroupId(), oneOf(messageEncoder).encodeMetadata(JOIN, message.getGroupId(),
message.getTimestamp(), false, false, false, false); message.getTimestamp(), false, false, false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
BdfMessageContext messageContext = BdfMessageContext messageContext =
@@ -404,7 +404,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
previousMessageId); previousMessageId);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder).encodeMetadata(JOIN, message.getGroupId(), oneOf(messageEncoder).encodeMetadata(JOIN, message.getGroupId(),
message.getTimestamp(), false, false, false, false); message.getTimestamp(), false, false, false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
BdfMessageContext messageContext = BdfMessageContext messageContext =
@@ -487,7 +487,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
BdfList body = BdfList.of(LEAVE.getValue(), privateGroup.getId(), null); BdfList body = BdfList.of(LEAVE.getValue(), privateGroup.getId(), null);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder).encodeMetadata(LEAVE, message.getGroupId(), oneOf(messageEncoder).encodeMetadata(LEAVE, message.getGroupId(),
message.getTimestamp(), false, false, false, false); message.getTimestamp(), false, false, false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
BdfMessageContext messageContext = BdfMessageContext messageContext =
@@ -500,7 +500,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
public void testAcceptsValidLeaveMessage() throws Exception { public void testAcceptsValidLeaveMessage() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder).encodeMetadata(LEAVE, message.getGroupId(), oneOf(messageEncoder).encodeMetadata(LEAVE, message.getGroupId(),
message.getTimestamp(), false, false, false, false); message.getTimestamp(), false, false, false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
BdfList body = BdfList.of(LEAVE.getValue(), privateGroup.getId(), BdfList body = BdfList.of(LEAVE.getValue(), privateGroup.getId(),
@@ -557,7 +557,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
public void testAcceptsValidAbortMessage() throws Exception { public void testAcceptsValidAbortMessage() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder).encodeMetadata(ABORT, message.getGroupId(), oneOf(messageEncoder).encodeMetadata(ABORT, message.getGroupId(),
message.getTimestamp(), false, false, false, false); message.getTimestamp(), false, false, false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
BdfList body = BdfList.of(ABORT.getValue(), privateGroup.getId()); BdfList body = BdfList.of(ABORT.getValue(), privateGroup.getId());

View File

@@ -3,11 +3,9 @@ package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.ProtocolStateException;
import org.briarproject.briar.api.privategroup.GroupMessage; import org.briarproject.briar.api.privategroup.GroupMessage;
@@ -132,15 +130,17 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
final JoinMessage properJoinMessage = final JoinMessage properJoinMessage =
new JoinMessage(messageId, contactGroupId, privateGroupId, new JoinMessage(messageId, contactGroupId, privateGroupId,
messageTimestamp, lastRemoteMessageId); messageTimestamp, lastRemoteMessageId);
final Message inviteMsg =
new Message(lastRemoteMessageId, contactGroupId, 1337L,
getRandomBytes(42));
final BdfList inviteList = BdfList.of("inviteMessage");
final long timestamp = 0L; final long timestamp = 0L;
final GroupMessage joinGroupMessage = final GroupMessage joinGroupMessage =
new GroupMessage(message, null, localAuthor); new GroupMessage(message, null, localAuthor);
final BdfDictionary meta = new BdfDictionary();
expectMarkMessageAvailableToAnswer(lastRemoteMessageId, false); expectMarkMessageAvailableToAnswer(lastRemoteMessageId, false);
context.checking(new Expectations() {{
oneOf(messageEncoder).setInvitationAccepted(meta, true);
oneOf(clientHelper)
.mergeMessageMetadata(txn, lastRemoteMessageId, meta);
}});
expectSendJoinMessage(properJoinMessage, true); expectSendJoinMessage(properJoinMessage, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageTracker).trackOutgoingMessage(txn, message); oneOf(messageTracker).trackOutgoingMessage(txn, message);

View File

@@ -136,6 +136,7 @@ public class ForumSharingIntegrationTest
assertEquals(forum0.getName(), invitation.getForumName()); assertEquals(forum0.getName(), invitation.getForumName());
assertEquals(contactId1From0, invitation.getContactId()); assertEquals(contactId1From0, invitation.getContactId());
assertEquals("Hi!", invitation.getMessage()); assertEquals("Hi!", invitation.getMessage());
assertTrue(invitation.canBeOpened());
} else { } else {
ForumInvitationResponse response = ForumInvitationResponse response =
(ForumInvitationResponse) m; (ForumInvitationResponse) m;
@@ -195,6 +196,7 @@ public class ForumSharingIntegrationTest
assertEquals(forum0.getName(), invitation.getForumName()); assertEquals(forum0.getName(), invitation.getForumName());
assertEquals(contactId1From0, invitation.getContactId()); assertEquals(contactId1From0, invitation.getContactId());
assertEquals(null, invitation.getMessage()); assertEquals(null, invitation.getMessage());
assertFalse(invitation.canBeOpened());
} else { } else {
ForumInvitationResponse response = ForumInvitationResponse response =
(ForumInvitationResponse) m; (ForumInvitationResponse) m;

View File

@@ -147,7 +147,7 @@ public abstract class SharingValidatorTest extends ValidatorTestCase {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder) oneOf(messageEncoder)
.encodeMetadata(type, groupId, timestamp, false, false, .encodeMetadata(type, groupId, timestamp, false, false,
false, false); false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
} }