mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Use client versioning for private groups.
This commit is contained in:
@@ -10,6 +10,7 @@ import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
@@ -28,6 +29,8 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
|
||||
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_VERSION;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
|
||||
import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
|
||||
@@ -45,6 +48,7 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
protected final PrivateGroupFactory privateGroupFactory;
|
||||
protected final MessageTracker messageTracker;
|
||||
|
||||
private final ClientVersioningManager clientVersioningManager;
|
||||
private final GroupMessageFactory groupMessageFactory;
|
||||
private final IdentityManager identityManager;
|
||||
private final MessageParser messageParser;
|
||||
@@ -52,6 +56,7 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
private final Clock clock;
|
||||
|
||||
AbstractProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
GroupMessageFactory groupMessageFactory,
|
||||
@@ -60,6 +65,7 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.privateGroupManager = privateGroupManager;
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.groupMessageFactory = groupMessageFactory;
|
||||
@@ -90,10 +96,14 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
return expected != null && dependency.equals(expected);
|
||||
}
|
||||
|
||||
void setPrivateGroupVisibility(Transaction txn, S session, Visibility v)
|
||||
throws DbException, FormatException {
|
||||
void setPrivateGroupVisibility(Transaction txn, S session,
|
||||
Visibility preferred) throws DbException, FormatException {
|
||||
// Apply min of preferred visibility and client's visibility
|
||||
ContactId contactId = getContactId(txn, session.getContactGroupId());
|
||||
db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), v);
|
||||
Visibility client = clientVersioningManager.getClientVisibility(txn,
|
||||
contactId, CLIENT_ID, CLIENT_VERSION);
|
||||
Visibility min = Visibility.min(preferred, client);
|
||||
db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), min);
|
||||
}
|
||||
|
||||
Message sendInviteMessage(Transaction txn, S session,
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
@@ -36,15 +37,16 @@ import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
|
||||
class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
||||
|
||||
CreatorProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
GroupMessageFactory groupMessageFactory,
|
||||
IdentityManager identityManager, MessageParser messageParser,
|
||||
MessageEncoder messageEncoder, MessageTracker messageTracker,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, clock);
|
||||
super(db, clientHelper, clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,19 +2,30 @@ package org.briarproject.briar.privategroup.invitation;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
enum CreatorState implements State {
|
||||
|
||||
START(0), INVITED(1), JOINED(2), LEFT(3), DISSOLVED(4), ERROR(5);
|
||||
START(0, INVISIBLE),
|
||||
INVITED(1, INVISIBLE),
|
||||
JOINED(2, SHARED),
|
||||
LEFT(3, INVISIBLE),
|
||||
DISSOLVED(4, INVISIBLE),
|
||||
ERROR(5, INVISIBLE);
|
||||
|
||||
private final int value;
|
||||
private final Visibility visibility;
|
||||
|
||||
CreatorState(int value) {
|
||||
CreatorState(int value, Visibility visibility) {
|
||||
this.value = value;
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -22,6 +33,11 @@ enum CreatorState implements State {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Visibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
static CreatorState fromValue(int value) throws FormatException {
|
||||
for (CreatorState s : values()) if (s.value == value) return s;
|
||||
throw new FormatException();
|
||||
|
||||
@@ -15,6 +15,7 @@ interface GroupInvitationConstants {
|
||||
String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted";
|
||||
|
||||
// Session keys
|
||||
String SESSION_KEY_IS_SESSION = "isSession";
|
||||
String SESSION_KEY_SESSION_ID = "sessionId";
|
||||
String SESSION_KEY_PRIVATE_GROUP_ID = "privateGroupId";
|
||||
String SESSION_KEY_LAST_LOCAL_MESSAGE_ID = "lastLocalMessageId";
|
||||
|
||||
@@ -16,7 +16,10 @@ import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Client;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager.ClientVersioningHook;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
@@ -36,15 +39,17 @@ import org.briarproject.briar.client.ConversationClientImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
|
||||
@@ -59,8 +64,12 @@ import static org.briarproject.briar.privategroup.invitation.Role.PEER;
|
||||
@NotNullByDefault
|
||||
class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
implements GroupInvitationManager, Client, ContactHook,
|
||||
PrivateGroupHook {
|
||||
PrivateGroupHook, ClientVersioningHook {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(GroupInvitationManagerImpl.class.getName());
|
||||
|
||||
private final ClientVersioningManager clientVersioningManager;
|
||||
private final ContactGroupFactory contactGroupFactory;
|
||||
private final PrivateGroupFactory privateGroupFactory;
|
||||
private final PrivateGroupManager privateGroupManager;
|
||||
@@ -73,8 +82,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
|
||||
@Inject
|
||||
GroupInvitationManagerImpl(DatabaseComponent db,
|
||||
ClientHelper clientHelper, MetadataParser metadataParser,
|
||||
MessageTracker messageTracker,
|
||||
ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
MetadataParser metadataParser, MessageTracker messageTracker,
|
||||
ContactGroupFactory contactGroupFactory,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
@@ -82,6 +92,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
SessionEncoder sessionEncoder,
|
||||
ProtocolEngineFactory engineFactory) {
|
||||
super(db, clientHelper, metadataParser, messageTracker);
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.contactGroupFactory = contactGroupFactory;
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.privateGroupManager = privateGroupManager;
|
||||
@@ -110,7 +121,11 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
Group g = getContactGroup(c);
|
||||
// Store the group and share it with the contact
|
||||
db.addGroup(txn, g);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||
Visibility client = clientVersioningManager.getClientVisibility(txn,
|
||||
c.getId(), CLIENT_ID, CLIENT_VERSION);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Applying visibility " + client + " to new contact group");
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), client);
|
||||
// Attach the contact ID to the group
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
|
||||
@@ -565,6 +580,72 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientVisibilityChanging(Transaction txn, Contact c,
|
||||
Visibility v) throws DbException {
|
||||
// Apply the client's visibility to the contact group
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Applying visibility " + v + " to contact group");
|
||||
Group g = getContactGroup(c);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), v);
|
||||
}
|
||||
|
||||
ClientVersioningHook getPrivateGroupClientVersioningHook() {
|
||||
return this::onPrivateGroupClientVisibilityChanging;
|
||||
}
|
||||
|
||||
private void onPrivateGroupClientVisibilityChanging(Transaction txn,
|
||||
Contact c, Visibility client) throws DbException {
|
||||
try {
|
||||
Collection<Group> shareables =
|
||||
db.getGroups(txn, PrivateGroupManager.CLIENT_ID,
|
||||
PrivateGroupManager.CLIENT_VERSION);
|
||||
Map<GroupId, Visibility> m = getPreferredVisibilities(txn, c);
|
||||
for (Group g : shareables) {
|
||||
Visibility preferred = m.get(g.getId());
|
||||
if (preferred == null) continue; // No session for this group
|
||||
// Apply min of preferred visibility and client's visibility
|
||||
Visibility min = Visibility.min(preferred, client);
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Applying visibility " + min
|
||||
+ " to private group, preferred " + preferred
|
||||
+ ", client " + client);
|
||||
}
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), min);
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<GroupId, Visibility> getPreferredVisibilities(Transaction txn,
|
||||
Contact c) throws DbException, FormatException {
|
||||
GroupId contactGroupId = getContactGroup(c).getId();
|
||||
BdfDictionary query = sessionParser.getAllSessionsQuery();
|
||||
Map<MessageId, BdfDictionary> results = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, contactGroupId, query);
|
||||
Map<GroupId, Visibility> m = new HashMap<>();
|
||||
for (BdfDictionary d : results.values()) {
|
||||
Role role = sessionParser.getRole(d);
|
||||
if (role == CREATOR) {
|
||||
CreatorSession s =
|
||||
sessionParser.parseCreatorSession(contactGroupId, d);
|
||||
m.put(s.getPrivateGroupId(), s.getState().getVisibility());
|
||||
} else if (role == INVITEE) {
|
||||
InviteeSession s =
|
||||
sessionParser.parseInviteeSession(contactGroupId, d);
|
||||
m.put(s.getPrivateGroupId(), s.getState().getVisibility());
|
||||
} else if (role == PEER) {
|
||||
PeerSession s =
|
||||
sessionParser.parsePeerSession(contactGroupId, d);
|
||||
m.put(s.getPrivateGroupId(), s.getState().getVisibility());
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
private static class StoredSession {
|
||||
|
||||
private final MessageId storageId;
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
||||
@@ -38,13 +39,25 @@ public class GroupInvitationModule {
|
||||
LifecycleManager lifecycleManager,
|
||||
ValidationManager validationManager, ContactManager contactManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
ConversationManager conversationManager) {
|
||||
ConversationManager conversationManager,
|
||||
ClientVersioningManager clientVersioningManager) {
|
||||
lifecycleManager.registerClient(groupInvitationManager);
|
||||
validationManager.registerIncomingMessageHook(CLIENT_ID, CLIENT_VERSION,
|
||||
groupInvitationManager);
|
||||
contactManager.registerContactHook(groupInvitationManager);
|
||||
privateGroupManager.registerPrivateGroupHook(groupInvitationManager);
|
||||
conversationManager.registerConversationClient(groupInvitationManager);
|
||||
clientVersioningManager.registerClient(CLIENT_ID, CLIENT_VERSION);
|
||||
clientVersioningManager.registerClientVersioningHook(CLIENT_ID,
|
||||
CLIENT_VERSION, groupInvitationManager);
|
||||
// The group invitation manager handles client visibility changes for
|
||||
// the private group manager
|
||||
clientVersioningManager.registerClient(PrivateGroupManager.CLIENT_ID,
|
||||
PrivateGroupManager.CLIENT_VERSION);
|
||||
clientVersioningManager.registerClientVersioningHook(
|
||||
PrivateGroupManager.CLIENT_ID,
|
||||
PrivateGroupManager.CLIENT_VERSION,
|
||||
groupInvitationManager.getPrivateGroupClientVersioningHook());
|
||||
return groupInvitationManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
@@ -41,15 +42,16 @@ import static org.briarproject.briar.privategroup.invitation.InviteeState.START;
|
||||
class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
||||
|
||||
InviteeProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
GroupMessageFactory groupMessageFactory,
|
||||
IdentityManager identityManager, MessageParser messageParser,
|
||||
MessageEncoder messageEncoder, MessageTracker messageTracker,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, clock);
|
||||
super(db, clientHelper, clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,6 +214,12 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
||||
throws DbException {
|
||||
// Send a LEAVE message
|
||||
Message sent = sendLeaveMessage(txn, s, false);
|
||||
try {
|
||||
// Make the private group invisible to the contact
|
||||
setPrivateGroupVisibility(txn, s, INVISIBLE);
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e); // Invalid group metadata
|
||||
}
|
||||
// Move to the LEFT state
|
||||
return new InviteeSession(s.getContactGroupId(), s.getPrivateGroupId(),
|
||||
sent.getId(), s.getLastRemoteMessageId(), sent.getTimestamp(),
|
||||
|
||||
@@ -2,20 +2,32 @@ package org.briarproject.briar.privategroup.invitation;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
enum InviteeState implements State {
|
||||
|
||||
START(0), INVITED(1), ACCEPTED(2), JOINED(3), LEFT(4), DISSOLVED(5),
|
||||
ERROR(6);
|
||||
START(0, INVISIBLE),
|
||||
INVITED(1, INVISIBLE),
|
||||
ACCEPTED(2, VISIBLE),
|
||||
JOINED(3, SHARED),
|
||||
LEFT(4, INVISIBLE),
|
||||
DISSOLVED(5, INVISIBLE),
|
||||
ERROR(6, INVISIBLE);
|
||||
|
||||
private final int value;
|
||||
private final Visibility visibility;
|
||||
|
||||
InviteeState(int value) {
|
||||
InviteeState(int value, Visibility visibility) {
|
||||
this.value = value;
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,6 +35,11 @@ enum InviteeState implements State {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Visibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
static InviteeState fromValue(int value) throws FormatException {
|
||||
for (InviteeState s : values()) if (s.value == value) return s;
|
||||
throw new FormatException();
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
@@ -36,15 +37,16 @@ import static org.briarproject.briar.privategroup.invitation.PeerState.START;
|
||||
class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
||||
|
||||
PeerProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
GroupMessageFactory groupMessageFactory,
|
||||
IdentityManager identityManager, MessageParser messageParser,
|
||||
MessageEncoder messageEncoder, MessageTracker messageTracker,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, clock);
|
||||
super(db, clientHelper, clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,20 +2,32 @@ package org.briarproject.briar.privategroup.invitation;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
enum PeerState implements State {
|
||||
|
||||
START(0), AWAIT_MEMBER(1), NEITHER_JOINED(2), LOCAL_JOINED(3),
|
||||
BOTH_JOINED(4), LOCAL_LEFT(5), ERROR(6);
|
||||
START(0, INVISIBLE),
|
||||
AWAIT_MEMBER(1, INVISIBLE),
|
||||
NEITHER_JOINED(2, INVISIBLE),
|
||||
LOCAL_JOINED(3, VISIBLE),
|
||||
BOTH_JOINED(4, SHARED),
|
||||
LOCAL_LEFT(5, INVISIBLE),
|
||||
ERROR(6, INVISIBLE);
|
||||
|
||||
private final int value;
|
||||
private final Visibility visibility;
|
||||
|
||||
PeerState(int value) {
|
||||
PeerState(int value, Visibility visibility) {
|
||||
this.value = value;
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,6 +35,11 @@ enum PeerState implements State {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Visibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
static PeerState fromValue(int value) throws FormatException {
|
||||
for (PeerState s : values()) if (s.value == value) return s;
|
||||
throw new FormatException();
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
@@ -19,6 +20,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final ClientHelper clientHelper;
|
||||
private final ClientVersioningManager clientVersioningManager;
|
||||
private final PrivateGroupManager privateGroupManager;
|
||||
private final PrivateGroupFactory privateGroupFactory;
|
||||
private final GroupMessageFactory groupMessageFactory;
|
||||
@@ -30,6 +32,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
|
||||
@Inject
|
||||
ProtocolEngineFactoryImpl(DatabaseComponent db, ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
GroupMessageFactory groupMessageFactory,
|
||||
@@ -38,6 +41,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.privateGroupManager = privateGroupManager;
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.groupMessageFactory = groupMessageFactory;
|
||||
@@ -50,21 +54,24 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
|
||||
@Override
|
||||
public ProtocolEngine<CreatorSession> createCreatorEngine() {
|
||||
return new CreatorProtocolEngine(db, clientHelper, privateGroupManager,
|
||||
return new CreatorProtocolEngine(db, clientHelper,
|
||||
clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolEngine<InviteeSession> createInviteeEngine() {
|
||||
return new InviteeProtocolEngine(db, clientHelper, privateGroupManager,
|
||||
return new InviteeProtocolEngine(db, clientHelper,
|
||||
clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolEngine<PeerSession> createPeerEngine() {
|
||||
return new PeerProtocolEngine(db, clientHelper, privateGroupManager,
|
||||
return new PeerProtocolEngine(db, clientHelper,
|
||||
clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_IS_SESSION;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
|
||||
@@ -28,6 +29,7 @@ class SessionEncoderImpl implements SessionEncoder {
|
||||
@Override
|
||||
public BdfDictionary encodeSession(Session s) {
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put(SESSION_KEY_IS_SESSION, true);
|
||||
d.put(SESSION_KEY_SESSION_ID, s.getPrivateGroupId());
|
||||
d.put(SESSION_KEY_PRIVATE_GROUP_ID, s.getPrivateGroupId());
|
||||
MessageId lastLocalMessageId = s.getLastLocalMessageId();
|
||||
|
||||
@@ -11,6 +11,8 @@ interface SessionParser {
|
||||
|
||||
BdfDictionary getSessionQuery(SessionId s);
|
||||
|
||||
BdfDictionary getAllSessionsQuery();
|
||||
|
||||
Role getRole(BdfDictionary d) throws FormatException;
|
||||
|
||||
CreatorSession parseCreatorSession(GroupId contactGroupId, BdfDictionary d)
|
||||
|
||||
@@ -13,6 +13,7 @@ import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_IS_SESSION;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
|
||||
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
|
||||
@@ -37,6 +38,11 @@ class SessionParserImpl implements SessionParser {
|
||||
return BdfDictionary.of(new BdfEntry(SESSION_KEY_SESSION_ID, s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdfDictionary getAllSessionsQuery() {
|
||||
return BdfDictionary.of(new BdfEntry(SESSION_KEY_IS_SESSION, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role getRole(BdfDictionary d) throws FormatException {
|
||||
return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue());
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package org.briarproject.briar.privategroup.invitation;
|
||||
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
|
||||
interface State {
|
||||
|
||||
int getValue();
|
||||
|
||||
Visibility getVisibility();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
@@ -24,6 +26,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||
import org.jmock.Expectations;
|
||||
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
@@ -47,6 +50,8 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
context.mock(DatabaseComponent.class);
|
||||
protected final ClientHelper clientHelper =
|
||||
context.mock(ClientHelper.class);
|
||||
protected final ClientVersioningManager clientVersioningManager =
|
||||
context.mock(ClientVersioningManager.class);
|
||||
protected final PrivateGroupFactory privateGroupFactory =
|
||||
context.mock(PrivateGroupFactory.class);
|
||||
protected final PrivateGroupManager privateGroupManager =
|
||||
@@ -181,10 +186,13 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
}});
|
||||
}
|
||||
|
||||
protected void expectSetPrivateGroupVisibility(Group.Visibility v)
|
||||
protected void expectSetPrivateGroupVisibility(Visibility v)
|
||||
throws Exception {
|
||||
expectGetContactId();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientVersioningManager).getClientVisibility(txn, contactId,
|
||||
CLIENT_ID, CLIENT_VERSION);
|
||||
will(returnValue(SHARED));
|
||||
oneOf(db).setGroupVisibility(txn, contactId, privateGroupId, v);
|
||||
}});
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ import static org.junit.Assert.assertEquals;
|
||||
public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
|
||||
private final CreatorProtocolEngine engine =
|
||||
new CreatorProtocolEngine(db, clientHelper, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
new CreatorProtocolEngine(db, clientHelper, clientVersioningManager,
|
||||
privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, clock);
|
||||
|
||||
private CreatorSession getDefaultSession(CreatorState state) {
|
||||
return new CreatorSession(contactGroupId, privateGroupId,
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.sync.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
@@ -69,6 +70,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||
private final ClientVersioningManager clientVersioningManager =
|
||||
context.mock(ClientVersioningManager.class);
|
||||
private final ContactGroupFactory contactGroupFactory =
|
||||
context.mock(ContactGroupFactory.class);
|
||||
private final PrivateGroupFactory privateGroupFactory =
|
||||
@@ -140,11 +143,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
}});
|
||||
MetadataParser metadataParser = context.mock(MetadataParser.class);
|
||||
MessageTracker messageTracker = context.mock(MessageTracker.class);
|
||||
groupInvitationManager =
|
||||
new GroupInvitationManagerImpl(db, clientHelper, metadataParser,
|
||||
messageTracker, contactGroupFactory,
|
||||
privateGroupFactory, privateGroupManager, messageParser,
|
||||
sessionParser, sessionEncoder, engineFactory);
|
||||
groupInvitationManager = new GroupInvitationManagerImpl(db,
|
||||
clientHelper, clientVersioningManager, metadataParser,
|
||||
messageTracker, contactGroupFactory, privateGroupFactory,
|
||||
privateGroupManager, messageParser, sessionParser,
|
||||
sessionEncoder, engineFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -184,6 +187,9 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
CLIENT_VERSION, c);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).addGroup(txn, contactGroup);
|
||||
oneOf(clientVersioningManager).getClientVisibility(txn, contactId,
|
||||
CLIENT_ID, CLIENT_VERSION);
|
||||
will(returnValue(SHARED));
|
||||
oneOf(db).setGroupVisibility(txn, c.getId(), contactGroup.getId(),
|
||||
SHARED);
|
||||
oneOf(clientHelper)
|
||||
|
||||
@@ -38,9 +38,10 @@ import static org.junit.Assert.assertTrue;
|
||||
public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
|
||||
private final InviteeProtocolEngine engine =
|
||||
new InviteeProtocolEngine(db, clientHelper, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
new InviteeProtocolEngine(db, clientHelper, clientVersioningManager,
|
||||
privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, clock);
|
||||
private final LocalAuthor localAuthor = getLocalAuthor();
|
||||
|
||||
private InviteeSession getDefaultSession(InviteeState state) {
|
||||
@@ -238,6 +239,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
@Test
|
||||
public void testOnLeaveActionFromAccepted() throws Exception {
|
||||
expectSendLeaveMessage(false);
|
||||
expectSetPrivateGroupVisibility(INVISIBLE);
|
||||
InviteeSession session = getDefaultSession(ACCEPTED);
|
||||
InviteeSession newSession = engine.onLeaveAction(txn, session);
|
||||
|
||||
@@ -249,6 +251,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
@Test
|
||||
public void testOnLeaveActionFromJoined() throws Exception {
|
||||
expectSendLeaveMessage(false);
|
||||
expectSetPrivateGroupVisibility(INVISIBLE);
|
||||
InviteeSession session = getDefaultSession(JOINED);
|
||||
InviteeSession newSession = engine.onLeaveAction(txn, session);
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@ import static org.junit.Assert.assertTrue;
|
||||
public class PeerProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
|
||||
private final PeerProtocolEngine engine =
|
||||
new PeerProtocolEngine(db, clientHelper, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker, clock);
|
||||
new PeerProtocolEngine(db, clientHelper, clientVersioningManager,
|
||||
privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, clock);
|
||||
|
||||
private PeerSession getDefaultSession(PeerState state) {
|
||||
return new PeerSession(contactGroupId, privateGroupId,
|
||||
|
||||
Reference in New Issue
Block a user