Prepare for new Forum Sharing Client

Methods for creating, adding and removing forums have been moved to the
`ForumManager`. In order to still handle removing forums properly, a
`RemoveForumHook` has been introduced.

Methods for sharing forums with all current and future contacts have
been removed along with the localGroup where this information was saved.

The `ShareForumActivity` now has the proper label.

The `SessionId` and the `ProtocolEngine` have been moved to the
`clients` package.

This addresses part of #322 and part of what has been discussed in #320.
This commit is contained in:
Torsten Grote
2016-04-26 16:37:40 -03:00
parent 189efe8d97
commit 9f9a216305
31 changed files with 144 additions and 162 deletions

View File

@@ -17,10 +17,12 @@ import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import org.briarproject.util.StringUtils;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -29,9 +31,12 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.inject.Inject;
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
import static org.briarproject.api.identity.Author.Status.ANONYMOUS;
import static org.briarproject.api.identity.Author.Status.UNKNOWN;
import static org.briarproject.api.identity.Author.Status.VERIFIED;
@@ -44,11 +49,19 @@ class ForumManagerImpl implements ForumManager {
private final DatabaseComponent db;
private final ClientHelper clientHelper;
private final GroupFactory groupFactory;
private final SecureRandom random;
private final List<RemoveForumHook> removeHooks;
@Inject
ForumManagerImpl(DatabaseComponent db, ClientHelper clientHelper) {
ForumManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
GroupFactory groupFactory, SecureRandom random) {
this.db = db;
this.clientHelper = clientHelper;
this.groupFactory = groupFactory;
this.random = random;
removeHooks = new CopyOnWriteArrayList<RemoveForumHook>();
}
@Override
@@ -56,6 +69,53 @@ class ForumManagerImpl implements ForumManager {
return CLIENT_ID;
}
@Override
public Forum createForum(String name) {
int length = StringUtils.toUtf8(name).length;
if (length == 0) throw new IllegalArgumentException();
if (length > MAX_FORUM_NAME_LENGTH)
throw new IllegalArgumentException();
byte[] salt = new byte[FORUM_SALT_LENGTH];
random.nextBytes(salt);
return createForum(name, salt);
}
@Override
public Forum createForum(String name, byte[] salt) {
try {
BdfList forum = BdfList.of(name, salt);
byte[] descriptor = clientHelper.toByteArray(forum);
Group g = groupFactory.createGroup(getClientId(), descriptor);
return new Forum(g, name, salt);
} catch (FormatException e) {
throw new RuntimeException(e);
}
}
@Override
public void addForum(Forum f) throws DbException {
Transaction txn = db.startTransaction(false);
try {
db.addGroup(txn, f.getGroup());
txn.setComplete();
} finally {
db.endTransaction(txn);
}
}
@Override
public void removeForum(Forum f) throws DbException {
Transaction txn = db.startTransaction(false);
try {
for (RemoveForumHook hook : removeHooks)
hook.removingForum(txn, f);
db.removeGroup(txn, f.getGroup());
txn.setComplete();
} finally {
db.endTransaction(txn);
}
}
@Override
public void addLocalPost(ForumPost p) throws DbException {
try {
@@ -190,10 +250,16 @@ class ForumManagerImpl implements ForumManager {
}
}
@Override
public void registerRemoveForumHook(RemoveForumHook hook) {
removeHooks.add(hook);
}
private Forum parseForum(Group g) throws FormatException {
byte[] descriptor = g.getDescriptor();
// Name, salt
BdfList forum = clientHelper.toList(descriptor, 0, descriptor.length);
return new Forum(g, forum.getString(0), forum.getRaw(1));
}
}

View File

@@ -10,9 +10,12 @@ import org.briarproject.api.forum.ForumPostFactory;
import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.ValidationManager;
import org.briarproject.api.system.Clock;
import java.security.SecureRandom;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -34,8 +37,9 @@ public class ForumModule {
@Provides
@Singleton
ForumManager provideForumManager(DatabaseComponent db,
ClientHelper clientHelper) {
return new ForumManagerImpl(db, clientHelper);
ClientHelper clientHelper,
GroupFactory groupFactory, SecureRandom random) {
return new ForumManagerImpl(db, clientHelper, groupFactory, random);
}
@Provides
@@ -75,12 +79,14 @@ public class ForumModule {
LifecycleManager lifecycleManager,
ContactManager contactManager,
ValidationManager validationManager,
ForumManager forumManager,
ForumSharingManagerImpl forumSharingManager) {
lifecycleManager.registerClient(forumSharingManager);
contactManager.registerAddContactHook(forumSharingManager);
contactManager.registerRemoveContactHook(forumSharingManager);
validationManager.registerIncomingMessageHook(
ForumSharingManagerImpl.CLIENT_ID, forumSharingManager);
forumManager.registerRemoveForumHook(forumSharingManager);
return forumSharingManager;
}
}

View File

@@ -19,7 +19,6 @@ import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
@@ -28,7 +27,6 @@ import org.briarproject.api.system.Clock;
import org.briarproject.util.StringUtils;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -40,12 +38,12 @@ import java.util.Set;
import javax.inject.Inject;
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.forum.ForumManager.RemoveForumHook;
class ForumSharingManagerImpl implements ForumSharingManager, Client,
AddContactHook, RemoveContactHook, IncomingMessageHook {
AddContactHook, RemoveContactHook, IncomingMessageHook,
RemoveForumHook {
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
"cd11a5d04dccd9e2931d6fc3df456313"
@@ -54,30 +52,23 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
private final DatabaseComponent db;
private final ForumManager forumManager;
private final ClientHelper clientHelper;
private final GroupFactory groupFactory;
private final PrivateGroupFactory privateGroupFactory;
private final SecureRandom random;
private final Clock clock;
private final Group localGroup;
@Inject
ForumSharingManagerImpl(DatabaseComponent db, ForumManager forumManager,
ClientHelper clientHelper, GroupFactory groupFactory,
PrivateGroupFactory privateGroupFactory, SecureRandom random,
ClientHelper clientHelper, PrivateGroupFactory privateGroupFactory,
Clock clock) {
this.db = db;
this.forumManager = forumManager;
this.clientHelper = clientHelper;
this.groupFactory = groupFactory;
this.privateGroupFactory = privateGroupFactory;
this.random = random;
this.clock = clock;
localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID);
}
@Override
public void createLocalState(Transaction txn) throws DbException {
db.addGroup(txn, localGroup);
// Ensure we've set things up for any pre-existing contacts
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
}
@@ -96,9 +87,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
BdfDictionary meta = new BdfDictionary();
meta.put("contactId", c.getId().getInt());
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
// Share any forums that are shared with all contacts
List<Forum> shared = getForumsSharedWithAllContacts(txn);
storeMessage(txn, g.getId(), shared, 0);
} catch (FormatException e) {
throw new DbException(e);
}
@@ -126,40 +114,10 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
}
@Override
public Forum createForum(String name) {
int length = StringUtils.toUtf8(name).length;
if (length == 0) throw new IllegalArgumentException();
if (length > MAX_FORUM_NAME_LENGTH)
throw new IllegalArgumentException();
byte[] salt = new byte[FORUM_SALT_LENGTH];
random.nextBytes(salt);
return createForum(name, salt);
}
@Override
public void addForum(Forum f) throws DbException {
Transaction txn = db.startTransaction(false);
public void removingForum(Transaction txn, Forum f) throws DbException {
try {
db.addGroup(txn, f.getGroup());
txn.setComplete();
} finally {
db.endTransaction(txn);
}
}
@Override
public void removeForum(Forum f) throws DbException {
try {
// Update the list shared with each contact
Transaction txn = db.startTransaction(false);
try {
for (Contact c : db.getContacts(txn))
removeFromList(txn, getContactGroup(c).getId(), f);
db.removeGroup(txn, f.getGroup());
txn.setComplete();
} finally {
db.endTransaction(txn);
}
for (Contact c : db.getContacts(txn))
removeFromList(txn, getContactGroup(c).getId(), f);
} catch (IOException e) {
throw new DbException(e);
}
@@ -247,8 +205,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
try {
// Retrieve the forum
Forum f = parseForum(db.getGroup(txn, g));
// Remove the forum from the list shared with all contacts
removeFromList(txn, localGroup.getId(), f);
// Update the list shared with each contact
shared = new HashSet<ContactId>(shared);
for (Contact c : db.getContacts(txn)) {
@@ -272,46 +228,10 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
}
}
@Override
public void setSharedWithAll(GroupId g) throws DbException {
try {
Transaction txn = db.startTransaction(false);
try {
// Retrieve the forum
Forum f = parseForum(db.getGroup(txn, g));
// Add the forum to the list shared with all contacts
addToList(txn, localGroup.getId(), f);
// Add the forum to the list shared with each contact
for (Contact c : db.getContacts(txn)) {
Group cg = getContactGroup(c);
if (addToList(txn, cg.getId(), f)) {
if (listContains(txn, cg.getId(), g, false))
db.setVisibleToContact(txn, c.getId(), g, true);
}
}
txn.setComplete();
} finally {
db.endTransaction(txn);
}
} catch (FormatException e) {
throw new DbException(e);
}
}
private Group getContactGroup(Contact c) {
return privateGroupFactory.createPrivateGroup(CLIENT_ID, c);
}
private List<Forum> getForumsSharedWithAllContacts(Transaction txn)
throws DbException, FormatException {
// Find the latest update in the local group
LatestUpdate latest = findLatest(txn, localGroup.getId(), true);
if (latest == null) return Collections.emptyList();
// Retrieve and parse the latest update
BdfList message = clientHelper.getMessageAsList(txn, latest.messageId);
return parseForumList(message);
}
private LatestUpdate findLatest(Transaction txn, GroupId g, boolean local)
throws DbException, FormatException {
LatestUpdate latest = null;
@@ -334,7 +254,8 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
for (int i = 0; i < forumList.size(); i++) {
// Name, salt
BdfList forum = forumList.getList(i);
forums.add(createForum(forum.getString(0), forum.getRaw(1)));
forums.add(forumManager
.createForum(forum.getString(0), forum.getRaw(1)));
}
return forums;
}
@@ -400,18 +321,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
}
}
private Forum createForum(String name, byte[] salt) {
try {
BdfList forum = BdfList.of(name, salt);
byte[] descriptor = clientHelper.toByteArray(forum);
Group g = groupFactory.createGroup(forumManager.getClientId(),
descriptor);
return new Forum(g, name, salt);
} catch (FormatException e) {
throw new RuntimeException(e);
}
}
private Forum parseForum(Group g) throws FormatException {
byte[] descriptor = g.getDescriptor();
// Name, salt

View File

@@ -1,7 +1,7 @@
package org.briarproject.introduction;
import org.briarproject.api.FormatException;
import org.briarproject.api.ProtocolEngine;
import org.briarproject.api.clients.ProtocolEngine;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.event.Event;
@@ -11,7 +11,7 @@ import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.introduction.IntroduceeAction;
import org.briarproject.api.introduction.IntroduceeProtocolState;
import org.briarproject.api.introduction.IntroductionRequest;
import org.briarproject.api.introduction.SessionId;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.sync.MessageId;
import java.util.ArrayList;

View File

@@ -1,7 +1,7 @@
package org.briarproject.introduction;
import org.briarproject.api.FormatException;
import org.briarproject.api.ProtocolEngine;
import org.briarproject.api.clients.ProtocolEngine;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.event.Event;
@@ -11,7 +11,7 @@ import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.introduction.IntroducerAction;
import org.briarproject.api.introduction.IntroducerProtocolState;
import org.briarproject.api.introduction.IntroductionResponse;
import org.briarproject.api.introduction.SessionId;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.sync.MessageId;
import java.util.ArrayList;

View File

@@ -20,7 +20,7 @@ import org.briarproject.api.introduction.IntroductionManager;
import org.briarproject.api.introduction.IntroductionMessage;
import org.briarproject.api.introduction.IntroductionRequest;
import org.briarproject.api.introduction.IntroductionResponse;
import org.briarproject.api.introduction.SessionId;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;

View File

@@ -5,7 +5,7 @@ import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.introduction.SessionId;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock;