Return actual private group message headers and bodies to the UI

This commit is contained in:
Torsten Grote
2016-10-20 17:54:52 -02:00
parent 2c8aaa215c
commit 349a34ffd8
6 changed files with 148 additions and 20 deletions

View File

@@ -3,19 +3,23 @@ package org.briarproject.api.privategroup;
import org.briarproject.api.clients.PostHeader; import org.briarproject.api.clients.PostHeader;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.Author.Status; import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class GroupMessageHeader extends PostHeader { public class GroupMessageHeader extends PostHeader {
private final GroupId groupId; private final GroupId groupId;
public GroupMessageHeader(@NotNull GroupId groupId, @NotNull MessageId id, public GroupMessageHeader(GroupId groupId, MessageId id,
@Nullable MessageId parentId, long timestamp, @Nullable MessageId parentId, long timestamp,
@NotNull Author author, @NotNull Status authorStatus, Author author, Status authorStatus, boolean read) {
boolean read) {
super(id, parentId, timestamp, author, authorStatus, read); super(id, parentId, timestamp, author, authorStatus, read);
this.groupId = groupId; this.groupId = groupId;
} }

View File

@@ -0,0 +1,21 @@
package org.briarproject.api.privategroup;
import org.briarproject.api.identity.Author;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import org.jetbrains.annotations.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class JoinMessageHeader extends GroupMessageHeader {
public JoinMessageHeader(GroupId groupId, MessageId id,
@Nullable MessageId parentId, long timestamp, Author author,
Author.Status authorStatus, boolean read) {
super(groupId, id, parentId, timestamp, author, authorStatus, read);
}
}

View File

@@ -8,6 +8,8 @@ interface Constants {
String KEY_TYPE = "type"; String KEY_TYPE = "type";
String KEY_TIMESTAMP = "timestamp"; String KEY_TIMESTAMP = "timestamp";
String KEY_READ = MSG_KEY_READ; String KEY_READ = MSG_KEY_READ;
String KEY_PARENT_ID = "parentId";
String KEY_AUTHOR_ID = "authorId";
String KEY_AUTHOR_NAME = "authorName"; String KEY_AUTHOR_NAME = "authorName";
String KEY_AUTHOR_PUBLIC_KEY = "authorPublicKey"; String KEY_AUTHOR_PUBLIC_KEY = "authorPublicKey";

View File

@@ -6,6 +6,8 @@ import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.privategroup.MessageType; import org.briarproject.api.privategroup.MessageType;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory; import org.briarproject.api.privategroup.PrivateGroupFactory;
@@ -24,8 +26,10 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENG
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH; import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_ID;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY;
import static org.briarproject.privategroup.Constants.KEY_PARENT_ID;
import static org.briarproject.privategroup.Constants.KEY_READ; import static org.briarproject.privategroup.Constants.KEY_READ;
import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP; import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP;
import static org.briarproject.privategroup.Constants.KEY_TYPE; import static org.briarproject.privategroup.Constants.KEY_TYPE;
@@ -33,12 +37,14 @@ import static org.briarproject.privategroup.Constants.KEY_TYPE;
class GroupMessageValidator extends BdfMessageValidator { class GroupMessageValidator extends BdfMessageValidator {
private final PrivateGroupFactory groupFactory; private final PrivateGroupFactory groupFactory;
private final AuthorFactory authorFactory;
GroupMessageValidator(PrivateGroupFactory groupFactory, GroupMessageValidator(PrivateGroupFactory groupFactory,
ClientHelper clientHelper, MetadataEncoder metadataEncoder, ClientHelper clientHelper, MetadataEncoder metadataEncoder,
Clock clock) { Clock clock, AuthorFactory authorFactory) {
super(clientHelper, metadataEncoder, clock); super(clientHelper, metadataEncoder, clock);
this.groupFactory = groupFactory; this.groupFactory = groupFactory;
this.authorFactory = authorFactory;
} }
@Override @Override
@@ -179,6 +185,7 @@ class GroupMessageValidator extends BdfMessageValidator {
// Return the metadata and dependencies // Return the metadata and dependencies
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
if (parent_id != null) meta.put(KEY_PARENT_ID, parent_id);
return new BdfMessageContext(meta, dependencies); return new BdfMessageContext(meta, dependencies);
} }
@@ -186,6 +193,8 @@ class GroupMessageValidator extends BdfMessageValidator {
byte[] pubKey, long time) { byte[] pubKey, long time) {
c.getDictionary().put(KEY_TIMESTAMP, time); c.getDictionary().put(KEY_TIMESTAMP, time);
c.getDictionary().put(KEY_READ, false); c.getDictionary().put(KEY_READ, false);
Author a = authorFactory.createAuthor(authorName, pubKey);
c.getDictionary().put(KEY_AUTHOR_ID, a.getId());
c.getDictionary().put(KEY_AUTHOR_NAME, authorName); c.getDictionary().put(KEY_AUTHOR_NAME, authorName);
c.getDictionary().put(KEY_AUTHOR_PUBLIC_KEY, pubKey); c.getDictionary().put(KEY_AUTHOR_PUBLIC_KEY, pubKey);
} }

View File

@@ -9,9 +9,13 @@ import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.privategroup.GroupMessage; import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.MessageType; import org.briarproject.api.privategroup.JoinMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory; import org.briarproject.api.privategroup.PrivateGroupFactory;
import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.PrivateGroupManager;
@@ -26,14 +30,23 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.api.identity.Author.Status.OURSELVES; import static org.briarproject.api.identity.Author.Status.OURSELVES;
import static org.briarproject.api.privategroup.MessageType.JOIN;
import static org.briarproject.api.privategroup.MessageType.NEW_MEMBER;
import static org.briarproject.api.privategroup.MessageType.POST;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_ID;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME;
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY;
import static org.briarproject.privategroup.Constants.KEY_PARENT_ID;
import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID; import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID;
import static org.briarproject.privategroup.Constants.KEY_READ; import static org.briarproject.privategroup.Constants.KEY_READ;
import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP; import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP;
@@ -49,17 +62,19 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
+ "67657220627920546f727374656e2047")); + "67657220627920546f727374656e2047"));
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final IdentityManager identityManager;
@Inject @Inject
PrivateGroupManagerImpl(ClientHelper clientHelper, PrivateGroupManagerImpl(ClientHelper clientHelper,
MetadataParser metadataParser, DatabaseComponent db, MetadataParser metadataParser, DatabaseComponent db,
PrivateGroupFactory privateGroupFactory) { PrivateGroupFactory privateGroupFactory,
IdentityManager identityManager) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser);
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.identityManager = identityManager;
} }
@NotNull
@Override @Override
public ClientId getClientId() { public ClientId getClientId() {
return CLIENT_ID; return CLIENT_ID;
@@ -85,14 +100,14 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
private void announceNewMember(Transaction txn, GroupMessage m) private void announceNewMember(Transaction txn, GroupMessage m)
throws DbException, FormatException { throws DbException, FormatException {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, MessageType.NEW_MEMBER.getInt()); meta.put(KEY_TYPE, NEW_MEMBER.getInt());
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
} }
private void joinPrivateGroup(Transaction txn, GroupMessage m) private void joinPrivateGroup(Transaction txn, GroupMessage m)
throws DbException, FormatException { throws DbException, FormatException {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, MessageType.JOIN.getInt()); meta.put(KEY_TYPE, JOIN.getInt());
addMessageMetadata(meta, m, true); addMessageMetadata(meta, m, true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage()); trackOutgoingMessage(txn, m.getMessage());
@@ -135,6 +150,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
clientHelper.mergeGroupMetadata(txn, g, d); clientHelper.mergeGroupMetadata(txn, g, d);
} }
@Override
public long getMessageTimestamp(MessageId id) throws DbException { public long getMessageTimestamp(MessageId id) throws DbException {
try { try {
BdfDictionary d = clientHelper.getMessageMetadataAsDictionary(id); BdfDictionary d = clientHelper.getMessageMetadataAsDictionary(id);
@@ -150,7 +166,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, MessageType.POST.getInt()); meta.put(KEY_TYPE, POST.getInt());
if (m.getParent() != null) meta.put(KEY_PARENT_ID, m.getParent());
addMessageMetadata(meta, m, true); addMessageMetadata(meta, m, true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage()); trackOutgoingMessage(txn, m.getMessage());
@@ -165,7 +182,6 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true); m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true);
} }
@NotNull
@Override @Override
public PrivateGroup getPrivateGroup(GroupId g) throws DbException { public PrivateGroup getPrivateGroup(GroupId g) throws DbException {
PrivateGroup privateGroup; PrivateGroup privateGroup;
@@ -179,7 +195,6 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
return privateGroup; return privateGroup;
} }
@NotNull
@Override @Override
public PrivateGroup getPrivateGroup(Transaction txn, GroupId g) public PrivateGroup getPrivateGroup(Transaction txn, GroupId g)
throws DbException { throws DbException {
@@ -191,7 +206,6 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
} }
} }
@NotNull
@Override @Override
public Collection<PrivateGroup> getPrivateGroups() throws DbException { public Collection<PrivateGroup> getPrivateGroups() throws DbException {
Collection<Group> groups; Collection<Group> groups;
@@ -219,18 +233,90 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
return false; return false;
} }
@NotNull
@Override @Override
public String getMessageBody(MessageId m) throws DbException { public String getMessageBody(MessageId m) throws DbException {
return "empty"; try {
// TODO remove
if (clientHelper.getMessageMetadataAsDictionary(m).getLong(KEY_TYPE) != POST.getInt())
return "new member joined";
// type(0), member_name(1), member_public_key(2), parent_id(3),
// previous_message_id(4), content(5), signature(6)
return clientHelper.getMessageAsList(m).getString(5);
} catch (FormatException e) {
throw new DbException(e);
}
} }
@NotNull
@Override @Override
public Collection<GroupMessageHeader> getHeaders(GroupId g) public Collection<GroupMessageHeader> getHeaders(GroupId g)
throws DbException { throws DbException {
Collection<GroupMessageHeader> headers =
new ArrayList<GroupMessageHeader>();
Transaction txn = db.startTransaction(true);
try {
Map<MessageId, BdfDictionary> metadata =
clientHelper.getMessageMetadataAsDictionary(txn, g);
// get all authors we need to get the status for
Set<AuthorId> authors = new HashSet<AuthorId>();
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
BdfDictionary meta = entry.getValue();
if (meta.getLong(KEY_TYPE) == NEW_MEMBER.getInt())
continue;
byte[] idBytes = meta.getRaw(KEY_AUTHOR_ID);
authors.add(new AuthorId(idBytes));
}
// get statuses for all authors
Map<AuthorId, Status> statuses = new HashMap<AuthorId, Status>();
for (AuthorId id : authors) {
statuses.put(id, identityManager.getAuthorStatus(txn, id));
}
// Parse the metadata
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
BdfDictionary meta = entry.getValue();
if (meta.getLong(KEY_TYPE) == NEW_MEMBER.getInt())
continue;
headers.add(getGroupMessageHeader(txn, g, entry.getKey(), meta,
statuses));
}
txn.setComplete();
return headers;
} catch (FormatException e) {
throw new DbException(e);
} finally {
db.endTransaction(txn);
}
}
return Collections.emptyList(); private GroupMessageHeader getGroupMessageHeader(Transaction txn, GroupId g,
MessageId id, BdfDictionary meta, Map<AuthorId, Status> statuses)
throws DbException, FormatException {
MessageId parentId = null;
if (meta.containsKey(KEY_PARENT_ID)) {
parentId = new MessageId(meta.getRaw(KEY_PARENT_ID));
}
long timestamp = meta.getLong(KEY_TIMESTAMP);
AuthorId authorId = new AuthorId(meta.getRaw(KEY_AUTHOR_ID));
String name = meta.getString(KEY_AUTHOR_NAME);
byte[] publicKey = meta.getRaw(KEY_AUTHOR_PUBLIC_KEY);
Author author = new Author(authorId, name, publicKey);
Status status;
if (statuses.containsKey(authorId)) {
status = statuses.get(authorId);
} else {
status = identityManager.getAuthorStatus(txn, author.getId());
}
boolean read = meta.getBoolean(KEY_READ);
if (meta.getLong(KEY_TYPE) == JOIN.getInt()) {
return new JoinMessageHeader(g, id, parentId, timestamp, author,
status, read);
}
return new GroupMessageHeader(g, id, parentId, timestamp, author,
status, read);
} }
@Override @Override
@@ -251,6 +337,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
boolean read) { boolean read) {
meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp()); meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp());
meta.put(KEY_READ, read); meta.put(KEY_READ, read);
meta.put(KEY_AUTHOR_ID, m.getMember().getId());
meta.put(KEY_AUTHOR_NAME, m.getMember().getName()); meta.put(KEY_AUTHOR_NAME, m.getMember().getName());
meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey()); meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey());
} }

View File

@@ -3,6 +3,7 @@ package org.briarproject.privategroup;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.messaging.ConversationManager; import org.briarproject.api.messaging.ConversationManager;
import org.briarproject.api.privategroup.GroupMessageFactory; import org.briarproject.api.privategroup.GroupMessageFactory;
@@ -59,11 +60,15 @@ public class PrivateGroupModule {
GroupMessageValidator provideGroupMessageValidator( GroupMessageValidator provideGroupMessageValidator(
PrivateGroupFactory groupFactory, PrivateGroupFactory groupFactory,
ValidationManager validationManager, ClientHelper clientHelper, ValidationManager validationManager, ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) { MetadataEncoder metadataEncoder, Clock clock,
AuthorFactory authorFactory) {
GroupMessageValidator validator = new GroupMessageValidator( GroupMessageValidator validator = new GroupMessageValidator(
groupFactory, clientHelper, metadataEncoder, clock); groupFactory, clientHelper, metadataEncoder, clock,
authorFactory);
validationManager.registerMessageValidator( validationManager.registerMessageValidator(
PrivateGroupManagerImpl.CLIENT_ID, validator); PrivateGroupManagerImpl.CLIENT_ID, validator);
return validator; return validator;
} }