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 469204c67..f6745af24 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 @@ -267,6 +267,16 @@ interface Database { */ Collection getContacts(T txn, AuthorId local) throws DbException; + /** + * Returns the contact with the given {@code handshakePublicKey} + * for the given local pseudonym or {@code null} if none exists. + *

+ * Read-only. + */ + @Nullable + Contact getContact(T txn, PublicKey handshakePublicKey, AuthorId local) + throws DbException; + /** * Returns the group with the given ID. *

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 f1e0d013c..2ad9f55d1 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 @@ -1465,6 +1465,43 @@ abstract class JdbcDatabase implements Database { } } + @Nullable + @Override + public Contact getContact(Connection txn, PublicKey handshakePublicKey, + AuthorId localAuthorId) throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT contactId, authorId, formatVersion, name," + + " alias, publicKey, verified" + + " FROM contacts" + + " WHERE handshakePublicKey = ? AND localAuthorId = ?"; + ps = txn.prepareStatement(sql); + ps.setBytes(1, handshakePublicKey.getEncoded()); + ps.setBytes(2, localAuthorId.getBytes()); + rs = ps.executeQuery(); + if (!rs.next()) return null; + ContactId contactId = new ContactId(rs.getInt(1)); + AuthorId authorId = new AuthorId(rs.getBytes(2)); + int formatVersion = rs.getInt(3); + String name = rs.getString(4); + String alias = rs.getString(5); + PublicKey publicKey = new SignaturePublicKey(rs.getBytes(6)); + boolean verified = rs.getBoolean(7); + if (rs.next()) throw new DbException(); + rs.close(); + ps.close(); + Author author = + new Author(authorId, formatVersion, name, publicKey); + return new Contact(contactId, author, localAuthorId, alias, + handshakePublicKey, verified); + } catch (SQLException e) { + tryToClose(rs, LOG, WARNING); + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public Group getGroup(Connection txn, GroupId g) throws DbException { PreparedStatement ps = null; diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index b8e246013..ac4231216 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -34,6 +34,7 @@ import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.SettableClock; import org.briarproject.bramble.test.TestDatabaseConfig; import org.briarproject.bramble.test.TestMessageFactory; +import org.briarproject.bramble.test.TestUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -1149,6 +1150,43 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.close(); } + @Test + public void testGetContactsByHandshakePublicKey() throws Exception { + Database db = open(false); + Connection txn = db.startTransaction(); + + // Add an identity for a local author - no contacts should be + // associated + db.addIdentity(txn, identity); + PublicKey handshakePublicKey = TestUtils.getSignaturePublicKey(); + Contact contact = + db.getContact(txn, handshakePublicKey, localAuthor.getId()); + assertNull(contact); + + // Add a contact associated with the local author + assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(), + handshakePublicKey, true)); + contact = db.getContact(txn, handshakePublicKey, localAuthor.getId()); + assertNotNull(contact); + assertEquals(contactId, contact.getId()); + assertEquals(author, contact.getAuthor()); + assertNull(contact.getAlias()); + assertEquals(handshakePublicKey, contact.getHandshakePublicKey()); + assertTrue(contact.isVerified()); + assertEquals(author.getName(), contact.getAuthor().getName()); + assertEquals(author.getPublicKey(), contact.getAuthor().getPublicKey()); + assertEquals(author.getFormatVersion(), + contact.getAuthor().getFormatVersion()); + + // Ensure no contacts are returned after contact was deleted + db.removeContact(txn, contactId); + contact = db.getContact(txn, handshakePublicKey, localAuthor.getId()); + assertNull(contact); + + db.commitTransaction(txn); + db.close(); + } + @Test public void testOfferedMessages() throws Exception { Database db = open(false);