From 47d95a52c818ac242aa0a59a9593da2beacadf7d Mon Sep 17 00:00:00 2001 From: goapunk <goapunk@riseup.net> Date: Thu, 30 Aug 2018 14:48:30 +0200 Subject: [PATCH] Add a table which tracks contact <-> mailbox relations --- .../bramble/api/db/DatabaseComponent.java | 16 +++++ .../bramble/api/mailbox/MailboxInfo.java | 41 ++++++++++++ .../org/briarproject/bramble/db/Database.java | 15 +++++ .../bramble/db/DatabaseComponentImpl.java | 19 ++++++ .../briarproject/bramble/db/JdbcDatabase.java | 66 +++++++++++++++++++ .../bramble/db/Migration39_40.java | 11 ++++ .../briar/test/TestDataCreatorImpl.java | 1 + 7 files changed, 169 insertions(+) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxInfo.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index ece42f725c..ed3bc3cf4a 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -7,6 +7,7 @@ import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.mailbox.MailboxInfo; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.settings.Settings; @@ -114,6 +115,13 @@ public interface DatabaseComponent { KeySetId addTransportKeys(Transaction txn, ContactId c, TransportKeys k) throws DbException; + /** + * Set the @{Link ContactType#CONTACT_MAILBOX} for a contact. + * key set ID. + */ + void setMailboxForContact(Transaction txn, ContactId c, @Nullable ContactId mailboxId, + @Nullable ContactId aliasId) throws DbException; + /** * Returns true if the database contains the given contact for the given * local pseudonym. @@ -235,6 +243,14 @@ public interface DatabaseComponent { Collection<ContactId> getContacts(Transaction txn, AuthorId a) throws DbException; + /** + * Returns @{MailboxInfo}s for all contact mailboxes. + * <p/> + * Read-only. + */ + Collection<MailboxInfo> getContactMailboxes(Transaction txn) + throws DbException; + /** * Returns the group with the given ID. * <p/> diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxInfo.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxInfo.java new file mode 100644 index 0000000000..0bd84867fb --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxInfo.java @@ -0,0 +1,41 @@ +package org.briarproject.bramble.api.mailbox; + +import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.Nullable; + +@NotNullByDefault +public class MailboxInfo { + + private final ContactId contactId; + // Null if the contact has no mailbox, our own will be used if possible. + @Nullable + private final ContactId mailboxId; + // The alias of the contact for the mailbox. The mailbox must not know + // the read id. + @Nullable + private final ContactId aliasId; + + public MailboxInfo(ContactId contactId, + ContactId mailboxId, + ContactId aliasId) { + this.contactId = contactId; + this.mailboxId = mailboxId; + this.aliasId = aliasId; + } + + public ContactId getContactId() { + return contactId; + } + + @Nullable + public ContactId getMailboxId() { + return mailboxId; + } + + @Nullable + public ContactId getAliasId() { + return aliasId; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index 3c0f476a6d..dd75128f88 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -13,6 +13,7 @@ import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.mailbox.MailboxInfo; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.settings.Settings; @@ -135,6 +136,13 @@ interface Database<T> { KeySetId addTransportKeys(T txn, ContactId c, TransportKeys k) throws DbException; + /** + * Set the @{Link ContactType#CONTACT_MAILBOX} for a contact. + * key set ID. + */ + void setMailboxForContact(T txn, ContactId c, @Nullable ContactId mailboxId, + @Nullable ContactId aliasId) throws DbException; + /** * Returns true if the database contains the given contact for the given * local pseudonym. @@ -246,6 +254,13 @@ interface Database<T> { */ Collection<ContactId> getContacts(T txn, AuthorId a) throws DbException; + /** + * Returns @{MailboxInfo}s for all contact mailboxes. + * <p/> + * Read-only. + */ + Collection<MailboxInfo> getContactMailboxes(T txn) throws DbException; + /** * Returns the amount of free storage space available to the database, in * bytes. This is based on the minimum of the space available on the device diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 76e68f696b..75832b9b02 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -27,6 +27,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent; import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent; import org.briarproject.bramble.api.lifecycle.ShutdownManager; +import org.briarproject.bramble.api.mailbox.MailboxInfo; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.settings.Settings; @@ -249,6 +250,17 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { return db.addTransportKeys(txn, c, k); } + @Override + public void setMailboxForContact(Transaction transaction, ContactId c, + @Nullable ContactId mailboxId, @Nullable ContactId aliasId) + throws DbException { + if (transaction.isReadOnly()) throw new IllegalArgumentException(); + T txn = unbox(transaction); + if (!db.containsContact(txn, c)) + throw new NoSuchContactException(); + db.setMailboxForContact(txn, c, mailboxId, aliasId); + } + @Override public boolean containsContact(Transaction transaction, AuthorId remote, AuthorId local) throws DbException { @@ -421,6 +433,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { return db.getContacts(txn, a); } + @Override + public Collection<MailboxInfo> getContactMailboxes(Transaction transaction) + throws DbException { + T txn = unbox(transaction); + return db.getContactMailboxes(txn); + } + @Override public Group getGroup(Transaction transaction, GroupId g) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index eadad3e42c..eb88aaf4f7 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.mailbox.MailboxInfo; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.settings.Settings; @@ -278,6 +279,19 @@ abstract class JdbcDatabase implements Database<Connection> { + " REFERENCES contacts (contactId)" + " ON DELETE CASCADE)"; + private static final String CREATE_MAILBOXES = + "CREATE TABLE mailboxes" + + " (contactId INT NOT NULL," + + " mailboxId INT," + + " aliasId INT," + + " PRIMARY KEY (contactId)," + + " FOREIGN KEY (contactId)" + + " REFERENCES contacts (contactId)" + + " ON DELETE CASCADE," + + " FOREIGN KEY (mailboxId)" + + " REFERENCES contacts (contactId)" + + " ON DELETE CASCADE)"; + private static final String INDEX_CONTACTS_BY_AUTHOR_ID = "CREATE INDEX IF NOT EXISTS contactsByAuthorId" + " ON contacts (authorId)"; @@ -439,6 +453,7 @@ abstract class JdbcDatabase implements Database<Connection> { s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS)); s.executeUpdate(insertTypeNames(CREATE_OUTGOING_KEYS)); s.executeUpdate(insertTypeNames(CREATE_INCOMING_KEYS)); + s.executeUpdate(insertTypeNames(CREATE_MAILBOXES)); s.close(); } catch (SQLException e) { tryToClose(s); @@ -970,6 +985,29 @@ abstract class JdbcDatabase implements Database<Connection> { } } + @Override + public void setMailboxForContact(Connection txn, ContactId contactId, + ContactId mailboxId, ContactId aliasId) + throws DbException { + PreparedStatement ps = null; + try { + String sql = "INSERT INTO mailboxes (contactId, mailboxId, aliasId)" + + " VALUES (?, ?, ?)"; + ps = txn.prepareStatement(sql); + ps.setInt(1, contactId.getInt()); + if (mailboxId == null) ps.setNull(2, INTEGER); + else ps.setInt(1, mailboxId.getInt()); + if (aliasId == null) ps.setNull(3, INTEGER); + else ps.setInt(3, aliasId.getInt()); + int affected = ps.executeUpdate(); + if (affected != 1) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps); + throw new DbException(e); + } + } + @Override public boolean containsContact(Connection txn, AuthorId remote, AuthorId local) throws DbException { @@ -1369,6 +1407,34 @@ abstract class JdbcDatabase implements Database<Connection> { } } + @Override + public Collection<MailboxInfo> getContactMailboxes(Connection txn) + throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT contactId, mailboxId, aliasId FROM mailboxes"; + ps = txn.prepareStatement(sql); + rs = ps.executeQuery(); + List<MailboxInfo> mailboxInfos = new ArrayList<>(); + while (rs.next()) { + int contactId = rs.getInt(1); + int mailboxid = rs.getInt(2); + int aliasId = rs.getInt(3); + mailboxInfos.add(new MailboxInfo(new ContactId(contactId), + mailboxid == 0 ? null : new ContactId(mailboxid), + aliasId == 0 ? null : new ContactId(aliasId))); + } + rs.close(); + ps.close(); + return mailboxInfos; + } catch (SQLException e) { + tryToClose(rs); + tryToClose(ps); + throw new DbException(e); + } + } + @Override public Group getGroup(Connection txn, GroupId g) throws DbException { PreparedStatement ps = null; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration39_40.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration39_40.java index ca86b1d067..ba9e56071a 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration39_40.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration39_40.java @@ -41,6 +41,17 @@ class Migration39_40 implements Migration<Connection> { // Set type NOT NULL s.execute("ALTER TABLE contacts" + " ALTER COLUMN type INT NOT NULL"); + s.execute("CREATE TABLE mailboxes" + + " (contactId INT NOT NULL," + + " mailboxId INT," + + " aliasId INT," + + " PRIMARY KEY (contactId)," + + " FOREIGN KEY (contactId)" + + " REFERENCES contacts (contactId)" + + " ON DELETE CASCADE," + + " FOREIGN KEY (mailboxId)" + + " REFERENCES contacts (contactId)" + + " ON DELETE CASCADE)"); } catch (SQLException e) { tryToClose(s); throw new DbException(e); diff --git a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java index 811f3a3510..56709159dc 100644 --- a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java @@ -173,6 +173,7 @@ public class TestDataCreatorImpl implements TestDataCreator { .addContact(txn, author, localAuthor.getId(), secretKey, timestamp, true, verified, true); transportPropertyManager.addRemoteProperties(txn, contactId, props); + db.setMailboxForContact(txn, contactId, null, contactId); contact = db.getContact(txn, contactId); db.commitTransaction(txn); } finally { -- GitLab