Look up auto-delete timer when creating private group invitation.

This commit is contained in:
akwizgran
2020-12-02 11:30:54 +00:00
committed by Torsten Grote
parent c9a9734368
commit 00ed6d9bb8
15 changed files with 98 additions and 72 deletions

View File

@@ -7,6 +7,7 @@ import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -16,6 +17,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.identity.AuthorManager;
import org.briarproject.briar.api.privategroup.GroupMessage;
@@ -52,6 +54,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
private final Executor cryptoExecutor;
private final TransactionManager db;
private final AutoDeleteManager autoDeleteManager;
private final ConversationManager conversationManager;
private final ContactManager contactManager;
private final IdentityManager identityManager;
@@ -67,6 +70,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
@DatabaseExecutor Executor dbExecutor,
@CryptoExecutor Executor cryptoExecutor,
TransactionManager db,
AutoDeleteManager autoDeleteManager,
ConversationManager conversationManager,
LifecycleManager lifecycleManager,
ContactManager contactManager,
@@ -81,6 +85,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
super(dbExecutor, lifecycleManager, contactManager, authorManager);
this.cryptoExecutor = cryptoExecutor;
this.db = db;
this.autoDeleteManager = autoDeleteManager;
this.conversationManager = conversationManager;
this.contactManager = contactManager;
this.identityManager = identityManager;
@@ -146,20 +151,10 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
runOnDbThread(() -> {
try {
db.transaction(true, txn -> {
List<InvitationContext> contexts = new ArrayList<>();
LocalAuthor localAuthor =
identityManager.getLocalAuthor(txn);
for (ContactId c : contactIds) {
try {
Contact contact = contactManager.getContact(txn, c);
long timestamp = conversationManager
.getTimestampForOutgoingMessage(txn, c);
contexts.add(
new InvitationContext(contact, timestamp));
} catch (NoSuchContactException e) {
// Continue
}
}
List<InvitationContext> contexts =
createInvitationContexts(txn, contactIds);
txn.attach(() -> signInvitations(g, localAuthor, contexts,
text, handler));
});
@@ -170,6 +165,23 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
});
}
private List<InvitationContext> createInvitationContexts(Transaction txn,
Collection<ContactId> contactIds) throws DbException {
List<InvitationContext> contexts = new ArrayList<>();
for (ContactId c : contactIds) {
try {
Contact contact = contactManager.getContact(txn, c);
long timestamp = conversationManager
.getTimestampForOutgoingMessage(txn, c);
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
contexts.add(new InvitationContext(contact, timestamp, timer));
} catch (NoSuchContactException e) {
// Continue
}
}
return contexts;
}
private void signInvitations(GroupId g, LocalAuthor localAuthor,
List<InvitationContext> contexts, @Nullable String text,
ResultExceptionHandler<Void, DbException> handler) {
@@ -188,12 +200,12 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
ResultExceptionHandler<Void, DbException> handler) {
runOnDbThread(() -> {
try {
for (InvitationContext context : contexts) {
for (InvitationContext ctx : contexts) {
try {
groupInvitationManager.sendInvitation(g,
context.contact.getId(), text,
context.timestamp,
requireNonNull(context.signature));
ctx.contact.getId(), text, ctx.timestamp,
requireNonNull(ctx.signature),
ctx.autoDeleteTimer);
} catch (NoSuchContactException e) {
// Continue
}
@@ -209,13 +221,15 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
private static class InvitationContext {
private final Contact contact;
private final long timestamp;
private final long timestamp, autoDeleteTimer;
@Nullable
private byte[] signature = null;
private InvitationContext(Contact contact, long timestamp) {
private InvitationContext(Contact contact, long timestamp,
long autoDeleteTimer) {
this.contact = contact;
this.timestamp = timestamp;
this.autoDeleteTimer = autoDeleteTimer;
}
}
}

View File

@@ -43,7 +43,8 @@ public interface GroupInvitationManager extends ConversationClient {
* pending.
*/
void sendInvitation(GroupId g, ContactId c, @Nullable String text,
long timestamp, byte[] signature) throws DbException;
long timestamp, byte[] signature, long autoDeleteTimer)
throws DbException;
/**
* Responds to a pending private group invitation from the given contact.

View File

@@ -115,8 +115,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
}
Message sendInviteMessage(Transaction txn, S s,
@Nullable String text, long timestamp, byte[] signature)
throws DbException {
@Nullable String text, long timestamp, byte[] signature,
long timer) throws DbException {
Group g = db.getGroup(txn, s.getPrivateGroupId());
PrivateGroup privateGroup;
try {
@@ -127,7 +127,6 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
Message m;
ContactId c = getContactId(txn, s.getContactGroupId());
if (contactSupportsAutoDeletion(txn, c)) {
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
privateGroup.getId(), timestamp, privateGroup.getName(),
privateGroup.getCreator(), privateGroup.getSalt(), text,

View File

@@ -61,11 +61,12 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
@Override
public CreatorSession onInviteAction(Transaction txn, CreatorSession s,
@Nullable String text, long timestamp, byte[] signature)
throws DbException {
@Nullable String text, long timestamp, byte[] signature,
long autoDeleteTimer) throws DbException {
switch (s.getState()) {
case START:
return onLocalInvite(txn, s, text, timestamp, signature);
return onLocalInvite(txn, s, text, timestamp, signature,
autoDeleteTimer);
case INVITED:
case JOINED:
case LEFT:
@@ -155,10 +156,11 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
}
private CreatorSession onLocalInvite(Transaction txn, CreatorSession s,
@Nullable String text, long timestamp, byte[] signature)
throws DbException {
@Nullable String text, long timestamp, byte[] signature,
long autoDeleteTimer) throws DbException {
// Send an INVITE message
Message sent = sendInviteMessage(txn, s, text, timestamp, signature);
Message sent = sendInviteMessage(txn, s, text, timestamp, signature,
autoDeleteTimer);
// Track the message
messageTracker.trackOutgoingMessage(txn, sent);
// Move to the INVITED state

View File

@@ -257,8 +257,8 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
@Override
public void sendInvitation(GroupId privateGroupId, ContactId c,
@Nullable String text, long timestamp, byte[] signature)
throws DbException {
@Nullable String text, long timestamp, byte[] signature,
long autoDeleteTimer) throws DbException {
SessionId sessionId = getSessionId(privateGroupId);
Transaction txn = db.startTransaction(false);
try {
@@ -281,7 +281,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
}
// Handle the invite action
session = creatorEngine.onInviteAction(txn, session, text,
timestamp, signature);
timestamp, signature, autoDeleteTimer);
// Store the updated session
storeSession(txn, storageId, session);
db.commitTransaction(txn);

View File

@@ -65,7 +65,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
@Override
public InviteeSession onInviteAction(Transaction txn, InviteeSession s,
@Nullable String text, long timestamp, byte[] signature) {
@Nullable String text, long timestamp, byte[] signature,
long autoDeleteTimer) {
throw new UnsupportedOperationException(); // Invalid in this role
}

View File

@@ -60,7 +60,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
@Override
public PeerSession onInviteAction(Transaction txn, PeerSession s,
@Nullable String text, long timestamp, byte[] signature) {
@Nullable String text, long timestamp, byte[] signature,
long autoDeleteTimer) {
throw new UnsupportedOperationException(); // Invalid in this role
}

View File

@@ -8,10 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
interface ProtocolEngine<S extends Session> {
interface ProtocolEngine<S extends Session<?>> {
S onInviteAction(Transaction txn, S session, @Nullable String text,
long timestamp, byte[] signature) throws DbException;
long timestamp, byte[] signature, long autoDeleteTimer)
throws DbException;
S onJoinAction(Transaction txn, S session) throws DbException;

View File

@@ -24,6 +24,7 @@ import java.util.Collection;
import javax.annotation.Nullable;
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
import static org.briarproject.briar.api.identity.AuthorInfo.Status.OURSELVES;
import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
@@ -220,8 +221,8 @@ public class PrivateGroupIntegrationTest
byte[] signature = groupInvitationFactory
.signInvitation(contact, groupId0, timestamp,
author0.getPrivateKey());
groupInvitationManager0
.sendInvitation(groupId0, c, text, timestamp, signature);
groupInvitationManager0.sendInvitation(groupId0, c, text, timestamp,
signature, NO_AUTO_DELETE_TIMER);
}
private GroupMember getGroupMember(PrivateGroupManager groupManager,

View File

@@ -129,8 +129,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
}
void expectSendInviteMessage(String text) throws Exception {
expectCheckWhetherContactSupportsAutoDeletion(true);
expectGetLocalTimestamp(messageTimestamp);
expectCheckWhetherContactSupportsAutoDeletion();
context.checking(new Expectations() {{
oneOf(messageEncoder).encodeInviteMessage(contactGroupId,
privateGroupId, inviteTimestamp, privateGroup.getName(),
@@ -143,8 +143,9 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
void expectSendJoinMessage(JoinMessage m, boolean visible)
throws Exception {
expectCheckWhetherContactSupportsAutoDeletion(visible);
expectGetLocalTimestamp(messageTimestamp);
expectCheckWhetherContactSupportsAutoDeletion();
if (visible) expectGetAutoDeleteTimer();
context.checking(new Expectations() {{
oneOf(messageEncoder).encodeJoinMessage(m.getContactGroupId(),
m.getPrivateGroupId(), m.getTimestamp(),
@@ -155,8 +156,9 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
}
void expectSendLeaveMessage(boolean visible) throws Exception {
expectCheckWhetherContactSupportsAutoDeletion(visible);
expectGetLocalTimestamp(messageTimestamp);
expectCheckWhetherContactSupportsAutoDeletion();
if (visible) expectGetAutoDeleteTimer();
context.checking(new Expectations() {{
oneOf(messageEncoder).encodeLeaveMessage(contactGroupId,
privateGroupId, messageTimestamp, lastLocalMessageId,
@@ -232,8 +234,7 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
}});
}
void expectCheckWhetherContactSupportsAutoDeletion(boolean visible)
throws Exception {
void expectCheckWhetherContactSupportsAutoDeletion() throws Exception {
context.checking(new Expectations() {{
oneOf(clientHelper).getContactId(txn, contactGroupId);
will(returnValue(contactId));
@@ -241,10 +242,13 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
GroupInvitationManager.CLIENT_ID,
GroupInvitationManager.MAJOR_VERSION);
will(returnValue(GroupInvitationManager.MINOR_VERSION));
if (visible) {
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
will(returnValue(NO_AUTO_DELETE_TIMER));
}
}});
}
void expectGetAutoDeleteTimer() throws Exception {
context.checking(new Expectations() {{
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
will(returnValue(NO_AUTO_DELETE_TIMER));
}});
}
}

View File

@@ -44,7 +44,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
expectOnLocalInvite(text);
CreatorSession newSession =
engine.onInviteAction(txn, session, text, inviteTimestamp,
signature);
signature, NO_AUTO_DELETE_TIMER);
assertEquals(INVITED, newSession.getState());
assertEquals(messageId, newSession.getLastLocalMessageId());
assertNull(newSession.getLastRemoteMessageId());
@@ -61,7 +61,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
expectOnLocalInvite(null);
CreatorSession newSession =
engine.onInviteAction(txn, session, null, inviteTimestamp,
signature);
signature, NO_AUTO_DELETE_TIMER);
assertEquals(INVITED, newSession.getState());
assertEquals(messageId, newSession.getLastLocalMessageId());
assertNull(newSession.getLastRemoteMessageId());
@@ -84,31 +84,31 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
@Test(expected = ProtocolStateException.class)
public void testOnInviteActionFromInvited() throws Exception {
engine.onInviteAction(txn, getDefaultSession(INVITED), null,
inviteTimestamp, signature);
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = ProtocolStateException.class)
public void testOnInviteActionFromJoined() throws Exception {
engine.onInviteAction(txn, getDefaultSession(JOINED), null,
inviteTimestamp, signature);
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = ProtocolStateException.class)
public void testOnInviteActionFromLeft() throws Exception {
engine.onInviteAction(txn, getDefaultSession(LEFT), null,
inviteTimestamp, signature);
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = ProtocolStateException.class)
public void testOnInviteActionFromDissolved() throws Exception {
engine.onInviteAction(txn, getDefaultSession(DISSOLVED), null,
inviteTimestamp, signature);
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = ProtocolStateException.class)
public void testOnInviteActionFromError() throws Exception {
engine.onInviteAction(txn, getDefaultSession(ERROR), null,
inviteTimestamp, signature);
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
// onJoinAction

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import javax.annotation.Nullable;
import static java.util.Collections.emptySet;
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -687,7 +688,8 @@ public class GroupInvitationIntegrationTest
byte[] signature = groupInvitationFactory.signInvitation(contact1From0,
privateGroup.getId(), timestamp, author0.getPrivateKey());
groupInvitationManager0.sendInvitation(privateGroup.getId(),
contactId1From0, text, timestamp, signature);
contactId1From0, text, timestamp, signature,
NO_AUTO_DELETE_TIMER);
}
}

View File

@@ -482,7 +482,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(creatorEngine).onInviteAction(with(txn),
with(any(CreatorSession.class)), with(text), with(time),
with(signature));
with(signature), with(NO_AUTO_DELETE_TIMER));
will(returnValue(creatorSession));
}});
expectStoreSession(creatorSession, storageMessage.getId());
@@ -491,7 +491,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
oneOf(db).endTransaction(txn);
}});
groupInvitationManager.sendInvitation(privateGroup.getId(), contactId,
text, time, signature);
text, time, signature, NO_AUTO_DELETE_TIMER);
}
@Test
@@ -514,7 +514,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
will(returnValue(creatorSession));
oneOf(creatorEngine).onInviteAction(with(txn),
with(any(CreatorSession.class)), with(text), with(time),
with(signature));
with(signature), with(NO_AUTO_DELETE_TIMER));
will(returnValue(creatorSession));
}});
expectStoreSession(creatorSession, storageMessage.getId());
@@ -523,7 +523,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
oneOf(db).endTransaction(txn);
}});
groupInvitationManager.sendInvitation(privateGroup.getId(), contactId,
text, time, signature);
text, time, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = IllegalArgumentException.class)

View File

@@ -58,43 +58,43 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromStart() {
engine.onInviteAction(txn, getDefaultSession(START), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromLeft() {
engine.onInviteAction(txn, getDefaultSession(ACCEPTED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromInvited() {
engine.onInviteAction(txn, getDefaultSession(INVITED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromDissolved() {
engine.onInviteAction(txn, getDefaultSession(DISSOLVED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromAccepted() {
engine.onInviteAction(txn, getDefaultSession(ACCEPTED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromJoined() {
engine.onInviteAction(txn, getDefaultSession(JOINED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromError() {
engine.onInviteAction(txn, getDefaultSession(ERROR), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
// onJoinAction

View File

@@ -40,43 +40,43 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest {
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromStart() {
engine.onInviteAction(txn, getDefaultSession(START), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromAwaitMember() {
engine.onInviteAction(txn, getDefaultSession(AWAIT_MEMBER), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromNeitherJoined() {
engine.onInviteAction(txn, getDefaultSession(NEITHER_JOINED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromLocalJoined() {
engine.onInviteAction(txn, getDefaultSession(LOCAL_JOINED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromBothJoined() {
engine.onInviteAction(txn, getDefaultSession(BOTH_JOINED), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromLocalLeft() {
engine.onInviteAction(txn, getDefaultSession(LOCAL_LEFT), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
@Test(expected = UnsupportedOperationException.class)
public void testOnInviteActionFromError() {
engine.onInviteAction(txn, getDefaultSession(ERROR), null,
messageTimestamp, signature);
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
}
// onJoinAction