Removed public/private groups from the wire protocol.

The distinction between inbox groups and other groups can be maintained
internally, there's no need to represent it on the wire.
This commit is contained in:
akwizgran
2013-12-20 13:32:36 +00:00
parent e8d864c004
commit 51b3a10be2
21 changed files with 139 additions and 199 deletions

View File

@@ -77,7 +77,7 @@ SelectContactsDialog.Listener {
setTitle(name); setTitle(name);
b = i.getByteArrayExtra("net.sf.briar.GROUP_SALT"); b = i.getByteArrayExtra("net.sf.briar.GROUP_SALT");
if(b == null) throw new IllegalStateException(); if(b == null) throw new IllegalStateException();
group = new Group(id, name, b, false); group = new Group(id, name, b);
subscribed = i.getBooleanExtra("net.sf.briar.SUBSCRIBED", false); subscribed = i.getBooleanExtra("net.sf.briar.SUBSCRIBED", false);
boolean all = i.getBooleanExtra("net.sf.briar.VISIBLE_TO_ALL", false); boolean all = i.getBooleanExtra("net.sf.briar.VISIBLE_TO_ALL", false);
@@ -208,8 +208,8 @@ SelectContactsDialog.Listener {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if(subscribe) { if(subscribe) {
if(!wasSubscribed) db.addGroup(group); if(!wasSubscribed) db.addGroup(group);
db.setVisibleToAll(group, all); db.setVisibleToAll(group.getId(), all);
if(!all) db.setVisibility(group, visible); if(!all) db.setVisibility(group.getId(), visible);
} else if(wasSubscribed) { } else if(wasSubscribed) {
db.removeGroup(group); db.removeGroup(group);
} }

View File

@@ -173,11 +173,11 @@ SelectContactsDialog.Listener {
public void run() { public void run() {
try { try {
lifecycleManager.waitForDatabase(); lifecycleManager.waitForDatabase();
Group g = groupFactory.createGroup(name, false); Group g = groupFactory.createGroup(name);
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
db.addGroup(g); db.addGroup(g);
if(all) db.setVisibleToAll(g, true); if(all) db.setVisibleToAll(g.getId(), true);
else db.setVisibility(g, visible); else db.setVisibility(g.getId(), visible);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO)) if(LOG.isLoggable(INFO))
LOG.info("Storing group took " + duration + " ms"); LOG.info("Storing group took " + duration + " ms");

View File

@@ -15,6 +15,8 @@ import static net.sf.briar.android.util.CommonLayoutParams.MATCH_WRAP_1;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -58,6 +60,9 @@ OnItemClickListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(GroupListActivity.class.getName()); Logger.getLogger(GroupListActivity.class.getName());
private final Map<GroupId,GroupId> groups =
new ConcurrentHashMap<GroupId,GroupId>();
private GroupListAdapter adapter = null; private GroupListAdapter adapter = null;
private ListView list = null; private ListView list = null;
private ListLoadingProgressBar loading = null; private ListLoadingProgressBar loading = null;
@@ -140,7 +145,6 @@ OnItemClickListener {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
for(GroupStatus s : db.getAvailableGroups()) { for(GroupStatus s : db.getAvailableGroups()) {
Group g = s.getGroup(); Group g = s.getGroup();
if(g.isPrivate()) continue;
if(s.isSubscribed()) { if(s.isSubscribed()) {
try { try {
Collection<MessageHeader> headers = Collection<MessageHeader> headers =
@@ -173,6 +177,7 @@ OnItemClickListener {
private void clearHeaders() { private void clearHeaders() {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
groups.clear();
list.setVisibility(GONE); list.setVisibility(GONE);
loading.setVisibility(VISIBLE); loading.setVisibility(VISIBLE);
adapter.clear(); adapter.clear();
@@ -185,10 +190,12 @@ OnItemClickListener {
final Collection<MessageHeader> headers) { final Collection<MessageHeader> headers) {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
GroupId id = g.getId();
groups.put(id, id);
list.setVisibility(VISIBLE); list.setVisibility(VISIBLE);
loading.setVisibility(GONE); loading.setVisibility(GONE);
// Remove the old item, if any // Remove the old item, if any
GroupListItem item = findGroup(g.getId()); GroupListItem item = findGroup(id);
if(item != null) adapter.remove(item); if(item != null) adapter.remove(item);
// Add a new item // Add a new item
adapter.add(new GroupListItem(g, headers)); adapter.add(new GroupListItem(g, headers));
@@ -243,7 +250,7 @@ OnItemClickListener {
public void eventOccurred(DatabaseEvent e) { public void eventOccurred(DatabaseEvent e) {
if(e instanceof MessageAddedEvent) { if(e instanceof MessageAddedEvent) {
Group g = ((MessageAddedEvent) e).getGroup(); Group g = ((MessageAddedEvent) e).getGroup();
if(!g.isPrivate()) { if(groups.containsKey(g.getId())) {
if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading"); if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
loadHeaders(g); loadHeaders(g);
} }
@@ -259,7 +266,7 @@ OnItemClickListener {
loadHeaders(); loadHeaders();
} else if(e instanceof SubscriptionRemovedEvent) { } else if(e instanceof SubscriptionRemovedEvent) {
Group g = ((SubscriptionRemovedEvent) e).getGroup(); Group g = ((SubscriptionRemovedEvent) e).getGroup();
if(!g.isPrivate()) { if(groups.containsKey(g.getId())) {
// Reload the group, expecting NoSuchSubscriptionException // Reload the group, expecting NoSuchSubscriptionException
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading"); if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
loadHeaders(g); loadHeaders(g);
@@ -299,6 +306,7 @@ OnItemClickListener {
public void run() { public void run() {
GroupListItem item = findGroup(g); GroupListItem item = findGroup(g);
if(item != null) { if(item != null) {
groups.remove(g);
adapter.remove(item); adapter.remove(item);
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
selectFirstUnread(); selectFirstUnread();
@@ -314,10 +322,8 @@ OnItemClickListener {
lifecycleManager.waitForDatabase(); lifecycleManager.waitForDatabase();
int available = 0; int available = 0;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
for(GroupStatus s : db.getAvailableGroups()) { for(GroupStatus s : db.getAvailableGroups())
if(!s.isSubscribed() && !s.getGroup().isPrivate()) if(!s.isSubscribed()) available++;
available++;
}
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO)) if(LOG.isLoggable(INFO))
LOG.info("Loading available took " + duration + " ms"); LOG.info("Loading available took " + duration + " ms");

View File

@@ -5,7 +5,6 @@ import static java.util.logging.Level.WARNING;
import static net.sf.briar.android.groups.ManageGroupsItem.NONE; import static net.sf.briar.android.groups.ManageGroupsItem.NONE;
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH; import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -76,10 +75,7 @@ implements DatabaseListener, OnItemClickListener {
try { try {
lifecycleManager.waitForDatabase(); lifecycleManager.waitForDatabase();
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Collection<GroupStatus> available = Collection<GroupStatus> available = db.getAvailableGroups();
new ArrayList<GroupStatus>();
for(GroupStatus s : db.getAvailableGroups())
if(!s.getGroup().isPrivate()) available.add(s);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO)) if(LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms"); LOG.info("Load took " + duration + " ms");

View File

@@ -35,6 +35,7 @@ import net.sf.briar.api.db.DbException;
import net.sf.briar.api.lifecycle.LifecycleManager; import net.sf.briar.api.lifecycle.LifecycleManager;
import net.sf.briar.api.messaging.Group; import net.sf.briar.api.messaging.Group;
import net.sf.briar.api.messaging.GroupId; import net.sf.briar.api.messaging.GroupId;
import net.sf.briar.api.messaging.GroupStatus;
import net.sf.briar.api.messaging.Message; import net.sf.briar.api.messaging.Message;
import net.sf.briar.api.messaging.MessageFactory; import net.sf.briar.api.messaging.MessageFactory;
import net.sf.briar.api.messaging.MessageId; import net.sf.briar.api.messaging.MessageId;
@@ -215,8 +216,8 @@ implements OnItemSelectedListener, OnClickListener {
lifecycleManager.waitForDatabase(); lifecycleManager.waitForDatabase();
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Collection<Group> groups = new ArrayList<Group>(); Collection<Group> groups = new ArrayList<Group>();
for(Group g : db.getGroups()) for(GroupStatus s : db.getAvailableGroups())
if(!g.isPrivate()) groups.add(g); if(s.isSubscribed()) groups.add(s.getGroup());
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO)) if(LOG.isLoggable(INFO))
LOG.info("Loading groups took " + duration + " ms"); LOG.info("Loading groups took " + duration + " ms");

View File

@@ -160,7 +160,10 @@ public interface DatabaseComponent {
Collection<TransportUpdate> generateTransportUpdates(ContactId c, Collection<TransportUpdate> generateTransportUpdates(ContactId c,
long maxLatency) throws DbException; long maxLatency) throws DbException;
/** Returns the status of all groups to which the user can subscribe. */ /**
* Returns the status of all groups to which the user subscribes or can
* subscribe, excluding inbox groups.
*/
Collection<GroupStatus> getAvailableGroups() throws DbException; Collection<GroupStatus> getAvailableGroups() throws DbException;
/** Returns the configuration for the given transport. */ /** Returns the configuration for the given transport. */
@@ -326,8 +329,8 @@ public interface DatabaseComponent {
long centre, byte[] bitmap) throws DbException; long centre, byte[] bitmap) throws DbException;
/** /**
* Makes a private group visible to the given contact, adds it to the * Makes a group visible to the given contact, adds it to the contact's
* contact's subscriptions, and sets it as the inbox group for the contact. * subscriptions, and sets it as the inbox group for the contact.
*/ */
public void setInboxGroup(ContactId c, Group g) throws DbException; public void setInboxGroup(ContactId c, Group g) throws DbException;
@@ -348,15 +351,15 @@ public interface DatabaseComponent {
void setSeen(ContactId c, Collection<MessageId> seen) throws DbException; void setSeen(ContactId c, Collection<MessageId> seen) throws DbException;
/** /**
* Makes a public group visible to the given set of contacts and invisible * Makes a group visible to the given set of contacts and invisible to any
* to any other current or future contacts. * other current or future contacts.
*/ */
void setVisibility(Group g, Collection<ContactId> visible) void setVisibility(GroupId g, Collection<ContactId> visible)
throws DbException; throws DbException;
/** /**
* Makes a public group visible to all current and future contacts, or * Makes a group visible to all current and future contacts, or invisible
* invisible to future contacts. * to future contacts.
*/ */
void setVisibleToAll(Group g, boolean all) throws DbException; void setVisibleToAll(GroupId g, boolean all) throws DbException;
} }

View File

@@ -6,13 +6,11 @@ public class Group {
private final GroupId id; private final GroupId id;
private final String name; private final String name;
private final byte[] salt; private final byte[] salt;
private final boolean isPrivate;
public Group(GroupId id, String name, byte[] salt, boolean isPrivate) { public Group(GroupId id, String name, byte[] salt) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.salt = salt; this.salt = salt;
this.isPrivate = isPrivate;
} }
/** Returns the group's unique identifier. */ /** Returns the group's unique identifier. */
@@ -33,11 +31,6 @@ public class Group {
return salt; return salt;
} }
/** Returns true if the group is private. */
public boolean isPrivate() {
return isPrivate;
}
@Override @Override
public int hashCode() { public int hashCode() {
return id.hashCode(); return id.hashCode();

View File

@@ -3,8 +3,8 @@ package net.sf.briar.api.messaging;
public interface GroupFactory { public interface GroupFactory {
/** Creates a group with the given name and a random salt. */ /** Creates a group with the given name and a random salt. */
Group createGroup(String name, boolean isPrivate); Group createGroup(String name);
/** Creates a group with the given name and salt. */ /** Creates a group with the given name and salt. */
Group createGroup(String name, byte[] salt, boolean isPrivate); Group createGroup(String name, byte[] salt);
} }

View File

@@ -152,11 +152,11 @@ interface Database<T> {
throws DbException; throws DbException;
/** /**
* Makes a public group visible to the given contact. * Makes a group visible to the given contact.
* <p> * <p>
* Locking: subscription write. * Locking: subscription write.
*/ */
void addVisibility(T txn, ContactId c, Group g) throws DbException; void addVisibility(T txn, ContactId c, GroupId g) throws DbException;
/** /**
* Returns true if the database contains the given contact. * Returns true if the database contains the given contact.
@@ -217,7 +217,8 @@ interface Database<T> {
throws DbException; throws DbException;
/** /**
* Returns the status of all groups to which the user can subscribe. * Returns the status of all groups to which the user subscribes or can
* subscribe, excluding inbox groups.
* <p> * <p>
* Locking: subscription read. * Locking: subscription read.
*/ */
@@ -522,15 +523,6 @@ interface Database<T> {
*/ */
Collection<ContactId> getVisibility(T txn, GroupId g) throws DbException; Collection<ContactId> getVisibility(T txn, GroupId g) throws DbException;
/**
* Returns the IDs of all private groups that are visible to the given
* contact.
* <p>
* Locking: subscription read.
*/
Collection<GroupId> getVisiblePrivateGroups(T txn, ContactId c)
throws DbException;
/** /**
* Increments the outgoing connection counter for the given endpoint * Increments the outgoing connection counter for the given endpoint
* in the given rotation period and returns the old value, or -1 if the * in the given rotation period and returns the old value, or -1 if the
@@ -616,11 +608,11 @@ interface Database<T> {
void removeTransport(T txn, TransportId t) throws DbException; void removeTransport(T txn, TransportId t) throws DbException;
/** /**
* Makes a public group invisible to the given contact. * Makes a group invisible to the given contact.
* <p> * <p>
* Locking: subscription write. * Locking: subscription write.
*/ */
void removeVisibility(T txn, ContactId c, Group g) throws DbException; void removeVisibility(T txn, ContactId c, GroupId g) throws DbException;
/** /**
* Sets the connection reordering window for the given endpoint in the * Sets the connection reordering window for the given endpoint in the
@@ -642,8 +634,8 @@ interface Database<T> {
long version) throws DbException; long version) throws DbException;
/** /**
* Makes a private group visible to the given contact, adds it to the * Makes a group visible to the given contact, adds it to the contact's
* contact's subscriptions, and sets it as the inbox group for the contact. * subscriptions, and sets it as the inbox group for the contact.
* <p> * <p>
* Locking: contact read, message write, subscription write. * Locking: contact read, message write, subscription write.
*/ */
@@ -732,11 +724,11 @@ interface Database<T> {
long version) throws DbException; long version) throws DbException;
/** /**
* Makes a public group visible or invisible to future contacts by default. * Makes a group visible or invisible to future contacts by default.
* <p> * <p>
* Locking: subscription write. * Locking: subscription write.
*/ */
void setVisibleToAll(T txn, Group g, boolean all) throws DbException; void setVisibleToAll(T txn, GroupId g, boolean all) throws DbException;
/** /**
* Updates the expiry times of the given messages with respect to the given * Updates the expiry times of the given messages with respect to the given

View File

@@ -1770,7 +1770,6 @@ DatabaseCleaner.Callback {
} }
public void setInboxGroup(ContactId c, Group g) throws DbException { public void setInboxGroup(ContactId c, Group g) throws DbException {
if(!g.isPrivate()) throw new IllegalArgumentException();
contactLock.readLock().lock(); contactLock.readLock().lock();
try { try {
messageLock.writeLock().lock(); messageLock.writeLock().lock();
@@ -1871,9 +1870,8 @@ DatabaseCleaner.Callback {
} }
} }
public void setVisibility(Group g, Collection<ContactId> visible) public void setVisibility(GroupId g, Collection<ContactId> visible)
throws DbException { throws DbException {
if(g.isPrivate()) throw new IllegalArgumentException();
Collection<ContactId> affected = new ArrayList<ContactId>(); Collection<ContactId> affected = new ArrayList<ContactId>();
contactLock.readLock().lock(); contactLock.readLock().lock();
try { try {
@@ -1881,12 +1879,11 @@ DatabaseCleaner.Callback {
try { try {
T txn = db.startTransaction(); T txn = db.startTransaction();
try { try {
if(!db.containsGroup(txn, g.getId())) if(!db.containsGroup(txn, g))
throw new NoSuchSubscriptionException(); throw new NoSuchSubscriptionException();
// Use HashSets for O(1) lookups, O(n) overall running time // Use HashSets for O(1) lookups, O(n) overall running time
HashSet<ContactId> now = new HashSet<ContactId>(visible); HashSet<ContactId> now = new HashSet<ContactId>(visible);
Collection<ContactId> before = Collection<ContactId> before = db.getVisibility(txn, g);
db.getVisibility(txn, g.getId());
before = new HashSet<ContactId>(before); before = new HashSet<ContactId>(before);
// Set the group's visibility for each current contact // Set the group's visibility for each current contact
for(ContactId c : db.getContactIds(txn)) { for(ContactId c : db.getContactIds(txn)) {
@@ -1917,8 +1914,7 @@ DatabaseCleaner.Callback {
callListeners(new LocalSubscriptionsUpdatedEvent(affected)); callListeners(new LocalSubscriptionsUpdatedEvent(affected));
} }
public void setVisibleToAll(Group g, boolean all) throws DbException { public void setVisibleToAll(GroupId g, boolean all) throws DbException {
if(g.isPrivate()) throw new IllegalArgumentException();
Collection<ContactId> affected = new ArrayList<ContactId>(); Collection<ContactId> affected = new ArrayList<ContactId>();
contactLock.readLock().lock(); contactLock.readLock().lock();
try { try {
@@ -1926,14 +1922,13 @@ DatabaseCleaner.Callback {
try { try {
T txn = db.startTransaction(); T txn = db.startTransaction();
try { try {
if(!db.containsGroup(txn, g.getId())) if(!db.containsGroup(txn, g))
throw new NoSuchSubscriptionException(); throw new NoSuchSubscriptionException();
// Make the group visible or invisible to future contacts // Make the group visible or invisible to future contacts
db.setVisibleToAll(txn, g, all); db.setVisibleToAll(txn, g, all);
if(all) { if(all) {
// Make the group visible to all current contacts // Make the group visible to all current contacts
Collection<ContactId> before = Collection<ContactId> before = db.getVisibility(txn, g);
db.getVisibility(txn, g.getId());
before = new HashSet<ContactId>(before); before = new HashSet<ContactId>(before);
for(ContactId c : db.getContactIds(txn)) { for(ContactId c : db.getContactIds(txn)) {
if(!before.contains(c)) { if(!before.contains(c)) {

View File

@@ -88,7 +88,6 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " (groupId HASH NOT NULL," + " (groupId HASH NOT NULL,"
+ " name VARCHAR NOT NULL," + " name VARCHAR NOT NULL,"
+ " salt BINARY NOT NULL," + " salt BINARY NOT NULL,"
+ " private BOOLEAN NOT NULL,"
+ " visibleToAll BOOLEAN NOT NULL," + " visibleToAll BOOLEAN NOT NULL,"
+ " PRIMARY KEY (groupId))"; + " PRIMARY KEY (groupId))";
@@ -112,7 +111,6 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " groupId HASH NOT NULL," // Not a foreign key + " groupId HASH NOT NULL," // Not a foreign key
+ " name VARCHAR NOT NULL," + " name VARCHAR NOT NULL,"
+ " salt BINARY NOT NULL," + " salt BINARY NOT NULL,"
+ " private BOOLEAN NOT NULL,"
+ " PRIMARY KEY (contactId, groupId)," + " PRIMARY KEY (contactId, groupId),"
+ " FOREIGN KEY (contactId)" + " FOREIGN KEY (contactId)"
+ " REFERENCES contacts (contactId)" + " REFERENCES contacts (contactId)"
@@ -646,13 +644,12 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "INSERT INTO groups" String sql = "INSERT INTO groups"
+ " (groupId, name, salt, private, visibleToAll)" + " (groupId, name, salt, visibleToAll)"
+ " VALUES (?, ?, ?, ?, FALSE)"; + " VALUES (?, ?, ?, FALSE)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getId().getBytes()); ps.setBytes(1, g.getId().getBytes());
ps.setString(2, g.getName()); ps.setString(2, g.getName());
ps.setBytes(3, g.getSalt()); ps.setBytes(3, g.getSalt());
ps.setBoolean(4, g.isPrivate());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException(); if(affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -900,9 +897,8 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public void addVisibility(Connection txn, ContactId c, Group g) public void addVisibility(Connection txn, ContactId c, GroupId g)
throws DbException { throws DbException {
if(g.isPrivate()) throw new IllegalArgumentException();
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "INSERT INTO groupVisibilities" String sql = "INSERT INTO groupVisibilities"
@@ -910,7 +906,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " VALUES (?, ?, FALSE)"; + " VALUES (?, ?, FALSE)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setBytes(2, g.getId().getBytes()); ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException(); if(affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -1120,9 +1116,12 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
// Add all subscribed groups to the list // Add all subscribed groups to the list, except inbox groups
String sql = "SELECT groupId, name, salt, private, visibleToAll" String sql = "SELECT DISTINCT g.groupId, name, salt, visibleToAll"
+ " FROM groups"; + " FROM groups AS g"
+ " LEFT OUTER JOIN groupVisibilities AS gv"
+ " ON g.groupId = gv.groupId"
+ " WHERE inbox = FALSE OR inbox IS NULL";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<GroupStatus> groups = new ArrayList<GroupStatus>(); List<GroupStatus> groups = new ArrayList<GroupStatus>();
@@ -1130,15 +1129,14 @@ abstract class JdbcDatabase implements Database<Connection> {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
byte[] salt = rs.getBytes(3); byte[] salt = rs.getBytes(3);
boolean isPrivate = rs.getBoolean(4); Group group = new Group(id, name, salt);
Group group = new Group(id, name, salt, isPrivate); boolean visibleToAll = rs.getBoolean(4);
boolean visibleToAll = rs.getBoolean(5);
groups.add(new GroupStatus(group, true, visibleToAll)); groups.add(new GroupStatus(group, true, visibleToAll));
} }
rs.close(); rs.close();
ps.close(); ps.close();
// Add all unsubscribed groups to the list // Add all unsubscribed groups to the list
sql = "SELECT DISTINCT cg.groupId, cg.name, cg.salt, cg.private" sql = "SELECT DISTINCT cg.groupId, cg.name, cg.salt"
+ " FROM contactGroups AS cg" + " FROM contactGroups AS cg"
+ " LEFT OUTER JOIN groups AS g" + " LEFT OUTER JOIN groups AS g"
+ " ON cg.groupId = g.groupId" + " ON cg.groupId = g.groupId"
@@ -1149,8 +1147,7 @@ abstract class JdbcDatabase implements Database<Connection> {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
byte[] salt = rs.getBytes(3); byte[] salt = rs.getBytes(3);
boolean isPrivate = rs.getBoolean(4); Group group = new Group(id, name, salt);
Group group = new Group(id, name, salt, isPrivate);
groups.add(new GroupStatus(group, false, false)); groups.add(new GroupStatus(group, false, false));
} }
rs.close(); rs.close();
@@ -1313,18 +1310,16 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT name, salt, private FROM groups" String sql = "SELECT name, salt FROM groups WHERE groupId = ?";
+ " WHERE groupId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
if(!rs.next()) throw new DbStateException(); if(!rs.next()) throw new DbStateException();
String name = rs.getString(1); String name = rs.getString(1);
byte[] salt = rs.getBytes(2); byte[] salt = rs.getBytes(2);
boolean isPrivate = rs.getBoolean(3);
rs.close(); rs.close();
ps.close(); ps.close();
return new Group(g, name, salt, isPrivate); return new Group(g, name, salt);
} catch(SQLException e) { } catch(SQLException e) {
tryToClose(rs); tryToClose(rs);
tryToClose(ps); tryToClose(ps);
@@ -1336,7 +1331,7 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT groupId, name, salt, private FROM groups"; String sql = "SELECT groupId, name, salt FROM groups";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Group> groups = new ArrayList<Group>(); List<Group> groups = new ArrayList<Group>();
@@ -1344,8 +1339,7 @@ abstract class JdbcDatabase implements Database<Connection> {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
byte[] salt = rs.getBytes(3); byte[] salt = rs.getBytes(3);
boolean isPrivate = rs.getBoolean(4); groups.add(new Group(id, name, salt));
groups.add(new Group(id, name, salt, isPrivate));
} }
rs.close(); rs.close();
ps.close(); ps.close();
@@ -2085,14 +2079,13 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT g.groupId, name, salt, private," String sql = "SELECT g.groupId, name, salt, localVersion, txCount"
+ " localVersion, txCount"
+ " FROM groups AS g" + " FROM groups AS g"
+ " JOIN groupVisibilities AS vis" + " JOIN groupVisibilities AS gvis"
+ " ON g.groupId = vis.groupId" + " ON g.groupId = gvis.groupId"
+ " JOIN groupVersions AS ver" + " JOIN groupVersions AS gver"
+ " ON vis.contactId = ver.contactId" + " ON gvis.contactId = gver.contactId"
+ " WHERE vis.contactId = ?" + " WHERE gvis.contactId = ?"
+ " AND localVersion > localAcked" + " AND localVersion > localAcked"
+ " AND expiry < ?"; + " AND expiry < ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
@@ -2106,10 +2099,9 @@ abstract class JdbcDatabase implements Database<Connection> {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
byte[] salt = rs.getBytes(3); byte[] salt = rs.getBytes(3);
boolean isPrivate = rs.getBoolean(4); groups.add(new Group(id, name, salt));
groups.add(new Group(id, name, salt, isPrivate)); version = rs.getLong(4);
version = rs.getLong(5); txCount = rs.getInt(5);
txCount = rs.getInt(6);
} }
rs.close(); rs.close();
ps.close(); ps.close();
@@ -2335,32 +2327,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public Collection<GroupId> getVisiblePrivateGroups(Connection txn,
ContactId c) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT g.groupId"
+ " FROM groups AS g"
+ " JOIN groupVisibilities AS gv"
+ " ON g.groupId = gv.groupId"
+ " WHERE contactId = ?"
+ " AND private = TRUE";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
rs = ps.executeQuery();
List<GroupId> visible = new ArrayList<GroupId>();
while(rs.next()) visible.add(new GroupId(rs.getBytes(1)));
rs.close();
ps.close();
return Collections.unmodifiableList(visible);
} catch(SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
public long incrementConnectionCounter(Connection txn, ContactId c, public long incrementConnectionCounter(Connection txn, ContactId c,
TransportId t, long period) throws DbException { TransportId t, long period) throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -2619,16 +2585,15 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public void removeVisibility(Connection txn, ContactId c, Group g) public void removeVisibility(Connection txn, ContactId c, GroupId g)
throws DbException { throws DbException {
if(g.isPrivate()) throw new IllegalArgumentException();
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "DELETE FROM groupVisibilities" String sql = "DELETE FROM groupVisibilities"
+ " WHERE contactId = ? AND groupId = ?"; + " WHERE contactId = ? AND groupId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setBytes(2, g.getId().getBytes()); ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException(); if(affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -2694,15 +2659,14 @@ abstract class JdbcDatabase implements Database<Connection> {
// Store the new subscriptions, if any // Store the new subscriptions, if any
if(groups.isEmpty()) return true; if(groups.isEmpty()) return true;
sql = "INSERT INTO contactGroups" sql = "INSERT INTO contactGroups"
+ " (contactId, groupId, name, salt, private)" + " (contactId, groupId, name, salt)"
+ " VALUES (?, ?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
for(Group g : groups) { for(Group g : groups) {
ps.setBytes(2, g.getId().getBytes()); ps.setBytes(2, g.getId().getBytes());
ps.setString(3, g.getName()); ps.setString(3, g.getName());
ps.setBytes(4, g.getSalt()); ps.setBytes(4, g.getSalt());
ps.setBoolean(5, g.isPrivate());
ps.addBatch(); ps.addBatch();
} }
int[] batchAffected = ps.executeBatch(); int[] batchAffected = ps.executeBatch();
@@ -2740,7 +2704,6 @@ abstract class JdbcDatabase implements Database<Connection> {
public void setInboxGroup(Connection txn, ContactId c, Group g) public void setInboxGroup(Connection txn, ContactId c, Group g)
throws DbException { throws DbException {
if(!g.isPrivate()) throw new IllegalArgumentException();
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
// Unset any existing inbox group for the contact // Unset any existing inbox group for the contact
@@ -2765,14 +2728,13 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.close(); ps.close();
// Add the group to the contact's subscriptions // Add the group to the contact's subscriptions
sql = "INSERT INTO contactGroups" sql = "INSERT INTO contactGroups"
+ " (contactId, groupId, name, salt, private)" + " (contactId, groupId, name, salt)"
+ " VALUES (?, ?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setBytes(2, g.getId().getBytes()); ps.setBytes(2, g.getId().getBytes());
ps.setString(3, g.getName()); ps.setString(3, g.getName());
ps.setBytes(4, g.getSalt()); ps.setBytes(4, g.getSalt());
ps.setBoolean(5, g.isPrivate());
affected = ps.executeUpdate(); affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException(); if(affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -3061,15 +3023,14 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public void setVisibleToAll(Connection txn, Group g, boolean all) public void setVisibleToAll(Connection txn, GroupId g, boolean all)
throws DbException { throws DbException {
if(g.isPrivate()) throw new IllegalArgumentException();
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "UPDATE groups SET visibleToAll = ? WHERE groupId = ?"; String sql = "UPDATE groups SET visibleToAll = ? WHERE groupId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBoolean(1, all); ps.setBoolean(1, all);
ps.setBytes(2, g.getId().getBytes()); ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if(affected > 1) throw new DbStateException(); if(affected > 1) throw new DbStateException();
ps.close(); ps.close();

View File

@@ -274,7 +274,7 @@ abstract class Connector extends Thread {
contactId = db.addContact(remoteAuthor, localAuthor.getId()); contactId = db.addContact(remoteAuthor, localAuthor.getId());
// Create and store the inbox group // Create and store the inbox group
byte[] salt = crypto.deriveGroupSalt(secret); byte[] salt = crypto.deriveGroupSalt(secret);
Group inbox = groupFactory.createGroup("Inbox", salt, true); Group inbox = groupFactory.createGroup("Inbox", salt);
db.addGroup(inbox); db.addGroup(inbox);
db.setInboxGroup(contactId, inbox); db.setInboxGroup(contactId, inbox);
// Store the remote transport properties // Store the remote transport properties

View File

@@ -27,20 +27,19 @@ class GroupFactoryImpl implements GroupFactory {
this.writerFactory = writerFactory; this.writerFactory = writerFactory;
} }
public Group createGroup(String name, boolean isPrivate) { public Group createGroup(String name) {
byte[] salt = new byte[GROUP_SALT_LENGTH]; byte[] salt = new byte[GROUP_SALT_LENGTH];
crypto.getSecureRandom().nextBytes(salt); crypto.getSecureRandom().nextBytes(salt);
return createGroup(name, salt, isPrivate); return createGroup(name, salt);
} }
public Group createGroup(String name, byte[] salt, boolean isPrivate) { public Group createGroup(String name, byte[] salt) {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out); Writer w = writerFactory.createWriter(out);
try { try {
w.writeStructStart(GROUP); w.writeStructStart(GROUP);
w.writeString(name); w.writeString(name);
w.writeBytes(salt); w.writeBytes(salt);
w.writeBoolean(isPrivate);
w.writeStructEnd(); w.writeStructEnd();
} catch(IOException e) { } catch(IOException e) {
// Shouldn't happen with ByteArrayOutputStream // Shouldn't happen with ByteArrayOutputStream
@@ -49,6 +48,6 @@ class GroupFactoryImpl implements GroupFactory {
MessageDigest messageDigest = crypto.getMessageDigest(); MessageDigest messageDigest = crypto.getMessageDigest();
messageDigest.update(out.toByteArray()); messageDigest.update(out.toByteArray());
GroupId id = new GroupId(messageDigest.digest()); GroupId id = new GroupId(messageDigest.digest());
return new Group(id, name, salt, isPrivate); return new Group(id, name, salt);
} }
} }

View File

@@ -31,11 +31,10 @@ class GroupReader implements StructReader<Group> {
byte[] publicKey = null; byte[] publicKey = null;
if(r.hasNull()) r.readNull(); if(r.hasNull()) r.readNull();
else publicKey = r.readBytes(MAX_PUBLIC_KEY_LENGTH); else publicKey = r.readBytes(MAX_PUBLIC_KEY_LENGTH);
boolean isPrivate = r.readBoolean();
r.readStructEnd(); r.readStructEnd();
r.removeConsumer(digesting); r.removeConsumer(digesting);
// Build and return the group // Build and return the group
GroupId id = new GroupId(messageDigest.digest()); GroupId id = new GroupId(messageDigest.digest());
return new Group(id, name, publicKey, isPrivate); return new Group(id, name, publicKey);
} }
} }

View File

@@ -122,7 +122,6 @@ class MessageFactoryImpl implements MessageFactory {
w.writeStructStart(GROUP); w.writeStructStart(GROUP);
w.writeString(g.getName()); w.writeString(g.getName());
w.writeBytes(g.getSalt()); w.writeBytes(g.getSalt());
w.writeBoolean(g.isPrivate());
w.writeStructEnd(); w.writeStructEnd();
} }

View File

@@ -129,7 +129,6 @@ class PacketWriterImpl implements PacketWriter {
w.writeStructStart(GROUP); w.writeStructStart(GROUP);
w.writeString(g.getName()); w.writeString(g.getName());
w.writeBytes(g.getSalt()); w.writeBytes(g.getSalt());
w.writeBoolean(g.isPrivate());
w.writeStructEnd(); w.writeStructEnd();
} }
w.writeListEnd(); w.writeListEnd();

View File

@@ -95,7 +95,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
new Random().nextBytes(secret); new Random().nextBytes(secret);
// Create a group // Create a group
GroupFactory groupFactory = i.getInstance(GroupFactory.class); GroupFactory groupFactory = i.getInstance(GroupFactory.class);
group = groupFactory.createGroup("Group", false); group = groupFactory.createGroup("Group");
// Create an author // Create an author
AuthorFactory authorFactory = i.getInstance(AuthorFactory.class); AuthorFactory authorFactory = i.getInstance(AuthorFactory.class);
CryptoComponent crypto = i.getInstance(CryptoComponent.class); CryptoComponent crypto = i.getInstance(CryptoComponent.class);

View File

@@ -83,7 +83,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
public DatabaseComponentTest() { public DatabaseComponentTest() {
groupId = new GroupId(TestUtils.getRandomId()); groupId = new GroupId(TestUtils.getRandomId());
group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH], false); group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH]);
authorId = new AuthorId(TestUtils.getRandomId()); authorId = new AuthorId(TestUtils.getRandomId());
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]); author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]);
localAuthorId = new AuthorId(TestUtils.getRandomId()); localAuthorId = new AuthorId(TestUtils.getRandomId());
@@ -465,9 +465,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
} catch(NoSuchContactException expected) {} } catch(NoSuchContactException expected) {}
try { try {
Group privateGroup = new Group(groupId, "Group", db.setInboxGroup(contactId, group);
new byte[GROUP_SALT_LENGTH], true);
db.setInboxGroup(contactId, privateGroup);
fail(); fail();
} catch(NoSuchContactException expected) {} } catch(NoSuchContactException expected) {}
@@ -559,7 +557,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
} catch(NoSuchSubscriptionException expected) {} } catch(NoSuchSubscriptionException expected) {}
try { try {
db.setVisibility(group, Collections.<ContactId>emptyList()); db.setVisibility(groupId, Collections.<ContactId>emptyList());
fail(); fail();
} catch(NoSuchSubscriptionException expected) {} } catch(NoSuchSubscriptionException expected) {}
@@ -1339,8 +1337,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(both)); will(returnValue(both));
oneOf(database).getContactIds(txn); oneOf(database).getContactIds(txn);
will(returnValue(both)); will(returnValue(both));
oneOf(database).removeVisibility(txn, contactId1, group); oneOf(database).removeVisibility(txn, contactId1, groupId);
oneOf(database).setVisibleToAll(txn, group, false); oneOf(database).setVisibleToAll(txn, groupId, false);
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
oneOf(listener).eventOccurred(with(any( oneOf(listener).eventOccurred(with(any(
LocalSubscriptionsUpdatedEvent.class))); LocalSubscriptionsUpdatedEvent.class)));
@@ -1349,7 +1347,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
shutdown); shutdown);
db.addListener(listener); db.addListener(listener);
db.setVisibility(group, Arrays.asList(contactId)); db.setVisibility(groupId, Arrays.asList(contactId));
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -1374,14 +1372,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(both)); will(returnValue(both));
oneOf(database).getContactIds(txn); oneOf(database).getContactIds(txn);
will(returnValue(both)); will(returnValue(both));
oneOf(database).setVisibleToAll(txn, group, false); oneOf(database).setVisibleToAll(txn, groupId, false);
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown); shutdown);
db.addListener(listener); db.addListener(listener);
db.setVisibility(group, both); db.setVisibility(groupId, both);
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -1407,8 +1405,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(Collections.emptyList())); will(returnValue(Collections.emptyList()));
oneOf(database).getContactIds(txn); oneOf(database).getContactIds(txn);
will(returnValue(both)); will(returnValue(both));
oneOf(database).addVisibility(txn, contactId, group); oneOf(database).addVisibility(txn, contactId, groupId);
oneOf(database).setVisibleToAll(txn, group, false); oneOf(database).setVisibleToAll(txn, groupId, false);
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
oneOf(listener).eventOccurred(with(any( oneOf(listener).eventOccurred(with(any(
LocalSubscriptionsUpdatedEvent.class))); LocalSubscriptionsUpdatedEvent.class)));
@@ -1417,12 +1415,12 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(txn)); will(returnValue(txn));
oneOf(database).containsGroup(txn, groupId); oneOf(database).containsGroup(txn, groupId);
will(returnValue(true)); will(returnValue(true));
oneOf(database).setVisibleToAll(txn, group, true); oneOf(database).setVisibleToAll(txn, groupId, true);
oneOf(database).getVisibility(txn, groupId); oneOf(database).getVisibility(txn, groupId);
will(returnValue(Arrays.asList(contactId))); will(returnValue(Arrays.asList(contactId)));
oneOf(database).getContactIds(txn); oneOf(database).getContactIds(txn);
will(returnValue(both)); will(returnValue(both));
oneOf(database).addVisibility(txn, contactId1, group); oneOf(database).addVisibility(txn, contactId1, groupId);
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
oneOf(listener).eventOccurred(with(any( oneOf(listener).eventOccurred(with(any(
LocalSubscriptionsUpdatedEvent.class))); LocalSubscriptionsUpdatedEvent.class)));
@@ -1431,8 +1429,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
shutdown); shutdown);
db.addListener(listener); db.addListener(listener);
db.setVisibility(group, Arrays.asList(contactId)); db.setVisibility(groupId, Arrays.asList(contactId));
db.setVisibleToAll(group, true); db.setVisibleToAll(groupId, true);
context.assertIsSatisfied(); context.assertIsSatisfied();
} }

View File

@@ -70,7 +70,7 @@ public class H2DatabaseTest extends BriarTestCase {
public H2DatabaseTest() throws Exception { public H2DatabaseTest() throws Exception {
groupId = new GroupId(TestUtils.getRandomId()); groupId = new GroupId(TestUtils.getRandomId());
group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH], false); group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH]);
authorId = new AuthorId(TestUtils.getRandomId()); authorId = new AuthorId(TestUtils.getRandomId());
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]); author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]);
localAuthorId = new AuthorId(TestUtils.getRandomId()); localAuthorId = new AuthorId(TestUtils.getRandomId());
@@ -166,7 +166,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
@@ -203,7 +203,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
db.addStatus(txn, contactId, messageId, false); db.addStatus(txn, contactId, messageId, false);
@@ -240,7 +240,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
db.addStatus(txn, contactId, messageId, false); db.addStatus(txn, contactId, messageId, false);
@@ -283,7 +283,7 @@ public class H2DatabaseTest extends BriarTestCase {
assertFalse(it.hasNext()); assertFalse(it.hasNext());
// Making the subscription visible should make the message sendable // Making the subscription visible should make the message sendable
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
assertTrue(db.containsSendableMessages(txn, contactId)); assertTrue(db.containsSendableMessages(txn, contactId));
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator(); it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
assertTrue(it.hasNext()); assertTrue(it.hasNext());
@@ -356,7 +356,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
db.addStatus(txn, contactId, messageId, false); db.addStatus(txn, contactId, messageId, false);
@@ -654,7 +654,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
// The message is not in the database // The message is not in the database
@@ -673,7 +673,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
@@ -697,7 +697,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.setRetentionTime(txn, contactId, timestamp + 1, 1); db.setRetentionTime(txn, contactId, timestamp + 1, 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
@@ -721,7 +721,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
@@ -746,7 +746,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
// The message is not in the database // The message is not in the database
@@ -784,7 +784,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
db.addStatus(txn, contactId, messageId, false); db.addStatus(txn, contactId, messageId, false);
@@ -826,7 +826,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
@@ -849,7 +849,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Arrays.asList(group), 1); db.setGroups(txn, contactId, Arrays.asList(group), 1);
db.addMessage(txn, message, false); db.addMessage(txn, message, false);
@@ -876,11 +876,11 @@ public class H2DatabaseTest extends BriarTestCase {
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId)); assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
// Make the group visible to the contact // Make the group visible to the contact
db.addVisibility(txn, contactId, group); db.addVisibility(txn, contactId, groupId);
assertEquals(Arrays.asList(contactId), db.getVisibility(txn, groupId)); assertEquals(Arrays.asList(contactId), db.getVisibility(txn, groupId));
// Make the group invisible again // Make the group invisible again
db.removeVisibility(txn, contactId, group); db.removeVisibility(txn, contactId, groupId);
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId)); assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -934,7 +934,7 @@ public class H2DatabaseTest extends BriarTestCase {
throws Exception { throws Exception {
GroupId groupId1 = new GroupId(TestUtils.getRandomId()); GroupId groupId1 = new GroupId(TestUtils.getRandomId());
Group group1 = new Group(groupId1, "Another group", Group group1 = new Group(groupId1, "Another group",
new byte[GROUP_SALT_LENGTH], false); new byte[GROUP_SALT_LENGTH]);
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
@@ -1134,7 +1134,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addGroup(txn, group); db.addGroup(txn, group);
GroupId groupId1 = new GroupId(TestUtils.getRandomId()); GroupId groupId1 = new GroupId(TestUtils.getRandomId());
Group group1 = new Group(groupId1, "Another group", Group group1 = new Group(groupId1, "Another group",
new byte[GROUP_SALT_LENGTH], false); new byte[GROUP_SALT_LENGTH]);
db.addGroup(txn, group1); db.addGroup(txn, group1);
// Store two messages in the first group // Store two messages in the first group
@@ -1188,7 +1188,7 @@ public class H2DatabaseTest extends BriarTestCase {
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
GroupId id = new GroupId(TestUtils.getRandomId()); GroupId id = new GroupId(TestUtils.getRandomId());
String name = "Group " + i; String name = "Group " + i;
groups.add(new Group(id, name, new byte[GROUP_SALT_LENGTH], false)); groups.add(new Group(id, name, new byte[GROUP_SALT_LENGTH]));
} }
Database<Connection> db = open(false); Database<Connection> db = open(false);
@@ -1201,12 +1201,13 @@ public class H2DatabaseTest extends BriarTestCase {
// Make the groups visible to the contact // Make the groups visible to the contact
Collections.shuffle(groups); Collections.shuffle(groups);
for(Group g : groups) db.addVisibility(txn, contactId, g); for(Group g : groups) db.addVisibility(txn, contactId, g.getId());
// Make some of the groups invisible to the contact and remove them all // Make some of the groups invisible to the contact and remove them all
Collections.shuffle(groups); Collections.shuffle(groups);
for(Group g : groups) { for(Group g : groups) {
if(Math.random() < 0.5) db.removeVisibility(txn, contactId, g); if(Math.random() < 0.5)
db.removeVisibility(txn, contactId, g.getId());
db.removeGroup(txn, g.getId()); db.removeGroup(txn, g.getId());
} }
@@ -1571,7 +1572,7 @@ public class H2DatabaseTest extends BriarTestCase {
// Make the group visible to all contacts - it should be available, // Make the group visible to all contacts - it should be available,
// subscribed, visible to all // subscribed, visible to all
db.setVisibleToAll(txn, group, true); db.setVisibleToAll(txn, groupId, true);
assertEquals(Arrays.asList(group), db.getGroups(txn)); assertEquals(Arrays.asList(group), db.getGroups(txn));
it = db.getAvailableGroups(txn).iterator(); it = db.getAvailableGroups(txn).iterator();
assertTrue(it.hasNext()); assertTrue(it.hasNext());
@@ -1636,10 +1637,8 @@ public class H2DatabaseTest extends BriarTestCase {
// Add a contact and an inbox group - no headers should be returned // Add a contact and an inbox group - no headers should be returned
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
Group inbox = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH], db.addGroup(txn, group);
true); db.setInboxGroup(txn, contactId, group);
db.addGroup(txn, inbox);
db.setInboxGroup(txn, contactId, inbox);
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
db.getInboxMessageHeaders(txn, contactId)); db.getInboxMessageHeaders(txn, contactId));

View File

@@ -121,7 +121,7 @@ public class ConstantsTest extends BriarTestCase {
MessageId parent = new MessageId(TestUtils.getRandomId()); MessageId parent = new MessageId(TestUtils.getRandomId());
// Create a maximum-length group // Create a maximum-length group
String groupName = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH); String groupName = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
Group group = groupFactory.createGroup(groupName, false); Group group = groupFactory.createGroup(groupName);
// Create a maximum-length author // Create a maximum-length author
String authorName = String authorName =
TestUtils.createRandomString(MAX_AUTHOR_NAME_LENGTH); TestUtils.createRandomString(MAX_AUTHOR_NAME_LENGTH);
@@ -180,7 +180,7 @@ public class ConstantsTest extends BriarTestCase {
Collection<Group> groups = new ArrayList<Group>(); Collection<Group> groups = new ArrayList<Group>();
for(int i = 0; i < MAX_SUBSCRIPTIONS; i++) { for(int i = 0; i < MAX_SUBSCRIPTIONS; i++) {
String name = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH); String name = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
groups.add(groupFactory.createGroup(name, false)); groups.add(groupFactory.createGroup(name));
} }
// Create a maximum-length subscription update // Create a maximum-length subscription update
SubscriptionUpdate u = new SubscriptionUpdate(groups, Long.MAX_VALUE); SubscriptionUpdate u = new SubscriptionUpdate(groups, Long.MAX_VALUE);

View File

@@ -69,7 +69,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
public SimplexMessagingIntegrationTest() throws Exception { public SimplexMessagingIntegrationTest() throws Exception {
GroupId groupId = new GroupId(TestUtils.getRandomId()); GroupId groupId = new GroupId(TestUtils.getRandomId());
group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH], true); group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH]);
transportId = new TransportId(TestUtils.getRandomId()); transportId = new TransportId(TestUtils.getRandomId());
// Create matching secrets for Alice and Bob // Create matching secrets for Alice and Bob
initialSecret = new byte[32]; initialSecret = new byte[32];