Merge branch '1538-create-handshake-key-pair' into 'master'

Generate and store handshake key pair at startup if necessary

Closes #1538

See merge request briar/briar!1082
This commit is contained in:
Torsten Grote
2019-05-14 15:39:44 +00:00
65 changed files with 886 additions and 577 deletions

View File

@@ -33,7 +33,8 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
/** /**
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* *
* @return whether or not this message should be shared * @param txn A read-write transaction
* @return Whether or not this message should be shared
* @throws DbException Should only be used for real database errors. * @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup, * If this is thrown, delivery will be attempted again at next startup,
* whereas if a FormatException is thrown, the message will be permanently * whereas if a FormatException is thrown, the message will be permanently

View File

@@ -159,8 +159,20 @@ public interface ContactManager {
interface ContactHook { interface ContactHook {
/**
* Called when a contact is being added.
*
* @param txn A read-write transaction
* @param c The contact that is being added
*/
void addingContact(Transaction txn, Contact c) throws DbException; void addingContact(Transaction txn, Contact c) throws DbException;
/**
* Called when a contact is being removed
*
* @param txn A read-write transaction
* @param c The contact that is being removed
*/
void removingContact(Transaction txn, Contact c) throws DbException; void removingContact(Transaction txn, Contact c) throws DbException;
} }
} }

View File

@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
@@ -128,9 +128,9 @@ public interface DatabaseComponent {
HandshakeKeys k) throws DbException; HandshakeKeys k) throws DbException;
/** /**
* Stores a local pseudonym. * Stores an identity.
*/ */
void addLocalAuthor(Transaction txn, LocalAuthor a) throws DbException; void addIdentity(Transaction txn, Identity i) throws DbException;
/** /**
* Stores a local message. * Stores a local message.
@@ -174,12 +174,12 @@ public interface DatabaseComponent {
boolean containsGroup(Transaction txn, GroupId g) throws DbException; boolean containsGroup(Transaction txn, GroupId g) throws DbException;
/** /**
* Returns true if the database contains the given local author. * Returns true if the database contains an identity for the given
* pseudonym.
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
boolean containsLocalAuthor(Transaction txn, AuthorId local) boolean containsIdentity(Transaction txn, AuthorId a) throws DbException;
throws DbException;
/** /**
* Returns true if the database contains the given pending contact. * Returns true if the database contains the given pending contact.
@@ -317,18 +317,18 @@ public interface DatabaseComponent {
throws DbException; throws DbException;
/** /**
* Returns the local pseudonym with the given ID. * Returns the identity for the local pseudonym with the given ID.
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
LocalAuthor getLocalAuthor(Transaction txn, AuthorId a) throws DbException; Identity getIdentity(Transaction txn, AuthorId a) throws DbException;
/** /**
* Returns all local pseudonyms. * Returns the identities for all local pseudonyms.
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
Collection<LocalAuthor> getLocalAuthors(Transaction txn) throws DbException; Collection<Identity> getIdentities(Transaction txn) throws DbException;
/** /**
* Returns the message with the given ID. * Returns the message with the given ID.
@@ -559,9 +559,9 @@ public interface DatabaseComponent {
HandshakeKeySetId k) throws DbException; HandshakeKeySetId k) throws DbException;
/** /**
* Removes a local pseudonym (and all associated state) from the database. * Removes an identity (and all associated state) from the database.
*/ */
void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException; void removeIdentity(Transaction txn, AuthorId a) throws DbException;
/** /**
* Removes a message (and all associated state) from the database. * Removes a message (and all associated state) from the database.
@@ -619,6 +619,12 @@ public interface DatabaseComponent {
void addMessageDependencies(Transaction txn, Message dependent, void addMessageDependencies(Transaction txn, Message dependent,
Collection<MessageId> dependencies) throws DbException; Collection<MessageId> dependencies) throws DbException;
/**
* Sets the handshake key pair for the identity with the given ID.
*/
void setHandshakeKeyPair(Transaction txn, AuthorId local, byte[] publicKey,
byte[] privateKey) throws DbException;
/** /**
* Sets the reordering window for the given transport key set in the given * Sets the reordering window for the given transport key set in the given
* time period. * time period.

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.api.db; package org.briarproject.bramble.api.db;
/** /**
* Thrown when a database operation is attempted for a pseudonym that is not in * Thrown when a database operation is attempted for an identity that is not in
* the database. This exception may occur due to concurrent updates and does * the database. This exception may occur due to concurrent updates and does
* not indicate a database error. * not indicate a database error.
*/ */
public class NoSuchLocalAuthorException extends DbException { public class NoSuchIdentityException extends DbException {
} }

View File

@@ -18,14 +18,7 @@ public interface AuthorFactory {
/** /**
* Creates a local author with the current format version and the given * Creates a local author with the current format version and the given
* name and keys. * name.
*/ */
LocalAuthor createLocalAuthor(String name, byte[] publicKey, LocalAuthor createLocalAuthor(String name);
byte[] privateKey);
/**
* Creates a local author with the given format version, name and keys.
*/
LocalAuthor createLocalAuthor(int formatVersion, String name,
byte[] publicKey, byte[] privateKey);
} }

View File

@@ -0,0 +1,96 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Arrays;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
@Immutable
@NotNullByDefault
public class Identity {
private final LocalAuthor localAuthor;
@Nullable
private final byte[] handshakePublicKey, handshakePrivateKey;
private final long created;
public Identity(LocalAuthor localAuthor,
@Nullable byte[] handshakePublicKey,
@Nullable byte[] handshakePrivateKey, long created) {
if (handshakePublicKey != null) {
int keyLength = handshakePublicKey.length;
if (keyLength == 0 || keyLength > MAX_AGREEMENT_PUBLIC_KEY_BYTES)
throw new IllegalArgumentException();
}
this.localAuthor = localAuthor;
this.handshakePublicKey = handshakePublicKey;
this.handshakePrivateKey = handshakePrivateKey;
this.created = created;
}
/**
* Returns the ID of the user's pseudonym.
*/
public AuthorId getId() {
return localAuthor.getId();
}
/**
* Returns the user's pseudonym.
*/
public LocalAuthor getLocalAuthor() {
return localAuthor;
}
/**
* Returns true if the identity has a handshake key pair.
*/
public boolean hasHandshakeKeyPair() {
return handshakePublicKey != null && handshakePrivateKey != null;
}
/**
* Returns the public key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePublicKey() {
return handshakePublicKey;
}
/**
* Returns the private key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePrivateKey() {
return handshakePrivateKey;
}
/**
* Returns the time the identity was created, in milliseconds since the
* Unix epoch.
*/
public long getTimeCreated() {
return created;
}
@Override
public int hashCode() {
return localAuthor.getId().hashCode();
}
@Override
public boolean equals(Object o) {
if (o instanceof Identity) {
Identity i = (Identity) o;
return created == i.created &&
localAuthor.equals(i.localAuthor) &&
Arrays.equals(handshakePublicKey, i.handshakePublicKey) &&
Arrays.equals(handshakePrivateKey, i.handshakePrivateKey);
}
return false;
}
}

View File

@@ -1,30 +1,29 @@
package org.briarproject.bramble.api.identity; package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.CryptoExecutor; import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault @NotNullByDefault
public interface IdentityManager { public interface IdentityManager {
/** /**
* Creates a local identity with the given name. * Creates an identity with the given name. The identity includes a
* handshake key pair.
*/ */
@CryptoExecutor @CryptoExecutor
LocalAuthor createLocalAuthor(String name); Identity createIdentity(String name);
/** /**
* Registers the given local identity with the manager. The identity is * Registers the given identity with the manager. This method should be
* not stored until {@link #storeLocalAuthor()} is called. * called before {@link LifecycleManager#startServices(SecretKey)}. The
* identity is stored when {@link LifecycleManager#startServices(SecretKey)}
* is called. The identity must include a handshake key pair.
*/ */
void registerLocalAuthor(LocalAuthor a); void registerIdentity(Identity i);
/**
* Stores the local identity registered with
* {@link #registerLocalAuthor(LocalAuthor)}, if any.
*/
void storeLocalAuthor() throws DbException;
/** /**
* Returns the cached local identity or loads it from the database. * Returns the cached local identity or loads it from the database.
@@ -33,7 +32,18 @@ public interface IdentityManager {
/** /**
* Returns the cached local identity or loads it from the database. * Returns the cached local identity or loads it from the database.
* <p/>
* Read-only.
*/ */
LocalAuthor getLocalAuthor(Transaction txn) throws DbException; LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/**
* Returns the cached handshake keys or loads them from the database.
* <p/>
* Read-only.
*
* @return A two-element array containing the public key in the first
* element and the private key in the second
*/
byte[][] getHandshakeKeys(Transaction txn) throws DbException;
} }

View File

@@ -2,11 +2,8 @@ package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
/** /**
* A pseudonym for the local user. * A pseudonym for the local user.
*/ */
@@ -15,31 +12,11 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
public class LocalAuthor extends Author { public class LocalAuthor extends Author {
private final byte[] privateKey; private final byte[] privateKey;
@Nullable
private final byte[] handshakePublicKey, handshakePrivateKey;
private final long created;
public LocalAuthor(AuthorId id, int formatVersion, String name, public LocalAuthor(AuthorId id, int formatVersion, String name,
byte[] publicKey, byte[] privateKey, long created) { byte[] publicKey, byte[] privateKey) {
super(id, formatVersion, name, publicKey); super(id, formatVersion, name, publicKey);
this.privateKey = privateKey; this.privateKey = privateKey;
this.created = created;
handshakePublicKey = null;
handshakePrivateKey = null;
}
public LocalAuthor(AuthorId id, int formatVersion, String name,
byte[] publicKey, byte[] privateKey, byte[] handshakePublicKey,
byte[] handshakePrivateKey, long created) {
super(id, formatVersion, name, publicKey);
if (handshakePublicKey.length == 0 ||
handshakePublicKey.length > MAX_PUBLIC_KEY_LENGTH) {
throw new IllegalArgumentException();
}
this.privateKey = privateKey;
this.handshakePublicKey = handshakePublicKey;
this.handshakePrivateKey = handshakePrivateKey;
this.created = created;
} }
/** /**
@@ -48,28 +25,4 @@ public class LocalAuthor extends Author {
public byte[] getPrivateKey() { public byte[] getPrivateKey() {
return privateKey; return privateKey;
} }
/**
* Returns the public key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePublicKey() {
return handshakePublicKey;
}
/**
* Returns the private key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePrivateKey() {
return handshakePrivateKey;
}
/**
* Returns the time the pseudonym was created, in milliseconds since the
* Unix epoch.
*/
public long getTimeCreated() {
return created;
}
} }

View File

@@ -7,15 +7,15 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
/** /**
* An event that is broadcast when a local pseudonym is added. * An event that is broadcast when an identity is added.
*/ */
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class LocalAuthorAddedEvent extends Event { public class IdentityAddedEvent extends Event {
private final AuthorId authorId; private final AuthorId authorId;
public LocalAuthorAddedEvent(AuthorId authorId) { public IdentityAddedEvent(AuthorId authorId) {
this.authorId = authorId; this.authorId = authorId;
} }

View File

@@ -7,15 +7,15 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
/** /**
* An event that is broadcast when a local pseudonym is removed. * An event that is broadcast when an identity is removed.
*/ */
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class LocalAuthorRemovedEvent extends Event { public class IdentityRemovedEvent extends Event {
private final AuthorId authorId; private final AuthorId authorId;
public LocalAuthorRemovedEvent(AuthorId authorId) { public IdentityRemovedEvent(AuthorId authorId) {
this.authorId = authorId; this.authorId = authorId;
} }

View File

@@ -2,16 +2,16 @@ package org.briarproject.bramble.api.lifecycle;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
/** /**
* Manages the lifecycle of the app, starting {@link Client Clients}, starting * Manages the lifecycle of the app: opening and closing the
* and stopping {@link Service Services}, shutting down * {@link DatabaseComponent} starting and stopping {@link Service Services},
* {@link ExecutorService ExecutorServices}, and opening and closing the * and shutting down {@link ExecutorService ExecutorServices}.
* {@link DatabaseComponent}.
*/ */
@NotNullByDefault @NotNullByDefault
public interface LifecycleManager { public interface LifecycleManager {
@@ -42,18 +42,19 @@ public interface LifecycleManager {
} }
} }
/**
* Registers a hook to be called after the database is opened and before
* {@link Service services} are started. This method should be called
* before {@link #startServices(SecretKey)}.
*/
void registerOpenDatabaseHook(OpenDatabaseHook hook);
/** /**
* Registers a {@link Service} to be started and stopped. This method * Registers a {@link Service} to be started and stopped. This method
* should be called before {@link #startServices(SecretKey)}. * should be called before {@link #startServices(SecretKey)}.
*/ */
void registerService(Service s); void registerService(Service s);
/**
* Registers a {@link Client} to be started. This method should be called
* before {@link #startServices(SecretKey)}.
*/
void registerClient(Client c);
/** /**
* Registers an {@link ExecutorService} to be shut down. This method * Registers an {@link ExecutorService} to be shut down. This method
* should be called before {@link #startServices(SecretKey)}. * should be called before {@link #startServices(SecretKey)}.
@@ -62,7 +63,7 @@ public interface LifecycleManager {
/** /**
* Opens the {@link DatabaseComponent} using the given key and starts any * Opens the {@link DatabaseComponent} using the given key and starts any
* registered {@link Client Clients} and {@link Service Services}. * registered {@link Service Services}.
*/ */
StartResult startServices(SecretKey dbKey); StartResult startServices(SecretKey dbKey);
@@ -80,8 +81,7 @@ public interface LifecycleManager {
/** /**
* Waits for the {@link DatabaseComponent} to be opened and all registered * Waits for the {@link DatabaseComponent} to be opened and all registered
* {@link Client Clients} and {@link Service Services} to start before * {@link Service Services} to start before returning.
* returning.
*/ */
void waitForStartup() throws InterruptedException; void waitForStartup() throws InterruptedException;
@@ -97,4 +97,13 @@ public interface LifecycleManager {
*/ */
LifecycleState getLifecycleState(); LifecycleState getLifecycleState();
interface OpenDatabaseHook {
/**
* Called when the database is being opened, before
* {@link #waitForDatabase()} returns.
*
* @param txn A read-write transaction
*/
void onDatabaseOpened(Transaction txn) throws DbException;
}
} }

View File

@@ -1,14 +0,0 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Client {
/**
* Called at startup to create any local state needed by the client.
*/
void createLocalState(Transaction txn) throws DbException;
}

View File

@@ -11,7 +11,8 @@ public interface IncomingMessageHook {
/** /**
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* *
* @return whether or not this message should be shared * @param txn A read-write transaction
* @return Whether or not this message should be shared
* @throws DbException Should only be used for real database errors. * @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup, * If this is thrown, delivery will be attempted again at next startup,
* whereas if an InvalidMessageException is thrown, * whereas if an InvalidMessageException is thrown,

View File

@@ -46,7 +46,14 @@ public interface ClientVersioningManager {
ClientId clientId, int majorVersion) throws DbException; ClientId clientId, int majorVersion) throws DbException;
interface ClientVersioningHook { interface ClientVersioningHook {
/**
* Called when the visibility of a client with respect to a contact is
* changing.
*
* @param txn A read-write transaction
* @param c The contact affected by the visibility change
* @param v The new visibility of the client
*/
void onClientVisibilityChanging(Transaction txn, Contact c, void onClientVisibilityChanging(Transaction txn, Contact c,
Visibility v) throws DbException; Visibility v) throws DbException;
} }

View File

@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
@@ -30,6 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -99,25 +101,26 @@ public class TestUtils {
return new SecretKey(getRandomBytes(SecretKey.LENGTH)); return new SecretKey(getRandomBytes(SecretKey.LENGTH));
} }
public static LocalAuthor getLocalAuthor() { public static Identity getIdentity() {
return getLocalAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH)); LocalAuthor localAuthor = getLocalAuthor();
} byte[] handshakePub = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
byte[] handshakePriv = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
public static LocalAuthor getLocalAuthor(int nameLength) { return new Identity(localAuthor, handshakePub, handshakePriv,
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey,
timestamp); timestamp);
} }
public static Author getAuthor() { public static LocalAuthor getLocalAuthor() {
return getAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH)); AuthorId id = new AuthorId(getRandomId());
int nameLength = 1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH);
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey);
} }
public static Author getAuthor(int nameLength) { public static Author getAuthor() {
AuthorId id = new AuthorId(getRandomId()); AuthorId id = new AuthorId(getRandomId());
int nameLength = 1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH);
String name = getRandomString(nameLength); String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Author(id, FORMAT_VERSION, name, publicKey); return new Author(id, FORMAT_VERSION, name, publicKey);

View File

@@ -4,8 +4,8 @@ import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
@@ -161,8 +161,8 @@ class AccountManagerImpl implements AccountManager {
synchronized (stateChangeLock) { synchronized (stateChangeLock) {
if (hasDatabaseKey()) if (hasDatabaseKey())
throw new AssertionError("Already have a database key"); throw new AssertionError("Already have a database key");
LocalAuthor localAuthor = identityManager.createLocalAuthor(name); Identity identity = identityManager.createIdentity(name);
identityManager.registerLocalAuthor(localAuthor); identityManager.registerIdentity(identity);
SecretKey key = crypto.generateSecretKey(); SecretKey key = crypto.generateSecretKey();
if (!encryptAndStoreDatabaseKey(key, password)) return false; if (!encryptAndStoreDatabaseKey(key, password)) return false;
databaseKey = key; databaseKey = key;

View File

@@ -15,7 +15,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
@@ -120,9 +120,9 @@ interface Database<T> {
HandshakeKeys k) throws DbException; HandshakeKeys k) throws DbException;
/** /**
* Stores a local pseudonym. * Stores an identity.
*/ */
void addLocalAuthor(T txn, LocalAuthor a) throws DbException; void addIdentity(T txn, Identity i) throws DbException;
/** /**
* Stores a message. * Stores a message.
@@ -187,11 +187,12 @@ interface Database<T> {
boolean containsGroup(T txn, GroupId g) throws DbException; boolean containsGroup(T txn, GroupId g) throws DbException;
/** /**
* Returns true if the database contains the given local pseudonym. * Returns true if the database contains an identity for the given
* pseudonym.
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
boolean containsLocalAuthor(T txn, AuthorId a) throws DbException; boolean containsIdentity(T txn, AuthorId a) throws DbException;
/** /**
* Returns true if the database contains the given message. * Returns true if the database contains the given message.
@@ -323,18 +324,18 @@ interface Database<T> {
throws DbException; throws DbException;
/** /**
* Returns the local pseudonym with the given ID. * Returns the identity for local pseudonym with the given ID.
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
LocalAuthor getLocalAuthor(T txn, AuthorId a) throws DbException; Identity getIdentity(T txn, AuthorId a) throws DbException;
/** /**
* Returns all local pseudonyms. * Returns the identities for all local pseudonyms.
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
Collection<LocalAuthor> getLocalAuthors(T txn) throws DbException; Collection<Identity> getIdentities(T txn) throws DbException;
/** /**
* Returns the message with the given ID. * Returns the message with the given ID.
@@ -629,9 +630,9 @@ interface Database<T> {
throws DbException; throws DbException;
/** /**
* Removes a local pseudonym (and all associated state) from the database. * Removes an identity (and all associated state) from the database.
*/ */
void removeLocalAuthor(T txn, AuthorId a) throws DbException; void removeIdentity(T txn, AuthorId a) throws DbException;
/** /**
* Removes a message (and all associated state) from the database. * Removes a message (and all associated state) from the database.
@@ -685,6 +686,12 @@ interface Database<T> {
void setGroupVisibility(T txn, ContactId c, GroupId g, boolean shared) void setGroupVisibility(T txn, ContactId c, GroupId g, boolean shared)
throws DbException; throws DbException;
/**
* Sets the handshake key pair for the identity with the given ID.
*/
void setHandshakeKeyPair(T txn, AuthorId local, byte[] publicKey,
byte[] privateKey) throws DbException;
/** /**
* Marks the given message as shared. * Marks the given message as shared.
*/ */

View File

@@ -20,7 +20,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.NoSuchGroupException; import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException; import org.briarproject.bramble.api.db.NoSuchIdentityException;
import org.briarproject.bramble.api.db.NoSuchMessageException; import org.briarproject.bramble.api.db.NoSuchMessageException;
import org.briarproject.bramble.api.db.NoSuchPendingContactException; import org.briarproject.bramble.api.db.NoSuchPendingContactException;
import org.briarproject.bramble.api.db.NoSuchTransportException; import org.briarproject.bramble.api.db.NoSuchTransportException;
@@ -32,9 +32,9 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventExecutor; import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent; import org.briarproject.bramble.api.identity.event.IdentityAddedEvent;
import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent; import org.briarproject.bramble.api.identity.event.IdentityRemovedEvent;
import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
@@ -237,9 +237,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throws DbException { throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, local)) if (!db.containsIdentity(txn, local))
throw new NoSuchLocalAuthorException(); throw new NoSuchIdentityException();
if (db.containsLocalAuthor(txn, remote.getId())) if (db.containsIdentity(txn, remote.getId()))
throw new ContactExistsException(); throw new ContactExistsException();
if (db.containsContact(txn, remote.getId(), local)) if (db.containsContact(txn, remote.getId(), local))
throw new ContactExistsException(); throw new ContactExistsException();
@@ -283,13 +283,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
@Override @Override
public void addLocalAuthor(Transaction transaction, LocalAuthor a) public void addIdentity(Transaction transaction, Identity i)
throws DbException { throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a.getId())) { if (!db.containsIdentity(txn, i.getId())) {
db.addLocalAuthor(txn, a); db.addIdentity(txn, i);
transaction.attach(new LocalAuthorAddedEvent(a.getId())); transaction.attach(new IdentityAddedEvent(i.getId()));
} }
} }
@@ -345,8 +345,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public boolean containsContact(Transaction transaction, AuthorId remote, public boolean containsContact(Transaction transaction, AuthorId remote,
AuthorId local) throws DbException { AuthorId local) throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, local)) if (!db.containsIdentity(txn, local))
throw new NoSuchLocalAuthorException(); throw new NoSuchIdentityException();
return db.containsContact(txn, remote, local); return db.containsContact(txn, remote, local);
} }
@@ -358,10 +358,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
@Override @Override
public boolean containsLocalAuthor(Transaction transaction, AuthorId local) public boolean containsIdentity(Transaction transaction, AuthorId a)
throws DbException { throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
return db.containsLocalAuthor(txn, local); return db.containsIdentity(txn, a);
} }
@Override @Override
@@ -505,8 +505,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public Collection<ContactId> getContacts(Transaction transaction, public Collection<ContactId> getContacts(Transaction transaction,
AuthorId a) throws DbException { AuthorId a) throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a)) if (!db.containsIdentity(txn, a))
throw new NoSuchLocalAuthorException(); throw new NoSuchIdentityException();
return db.getContacts(txn, a); return db.getContacts(txn, a);
} }
@@ -554,19 +554,19 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
@Override @Override
public LocalAuthor getLocalAuthor(Transaction transaction, AuthorId a) public Identity getIdentity(Transaction transaction, AuthorId a)
throws DbException { throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a)) if (!db.containsIdentity(txn, a))
throw new NoSuchLocalAuthorException(); throw new NoSuchIdentityException();
return db.getLocalAuthor(txn, a); return db.getIdentity(txn, a);
} }
@Override @Override
public Collection<LocalAuthor> getLocalAuthors(Transaction transaction) public Collection<Identity> getIdentities(Transaction transaction)
throws DbException { throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
return db.getLocalAuthors(txn); return db.getIdentities(txn);
} }
@Override @Override
@@ -905,14 +905,14 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
@Override @Override
public void removeLocalAuthor(Transaction transaction, AuthorId a) public void removeIdentity(Transaction transaction, AuthorId a)
throws DbException { throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a)) if (!db.containsIdentity(txn, a))
throw new NoSuchLocalAuthorException(); throw new NoSuchIdentityException();
db.removeLocalAuthor(txn, a); db.removeIdentity(txn, a);
transaction.attach(new LocalAuthorRemovedEvent(a)); transaction.attach(new IdentityRemovedEvent(a));
} }
@Override @Override
@@ -1035,6 +1035,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
} }
@Override
public void setHandshakeKeyPair(Transaction transaction, AuthorId local,
byte[] publicKey, byte[] privateKey) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsIdentity(txn, local))
throw new NoSuchIdentityException();
db.setHandshakeKeyPair(txn, local, publicKey, privateKey);
}
@Override @Override
public void setReorderingWindow(Transaction transaction, public void setReorderingWindow(Transaction transaction,
TransportKeySetId k, TransportId t, long timePeriod, long base, TransportKeySetId k, TransportId t, long timePeriod, long base,

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
@@ -874,8 +875,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public void addLocalAuthor(Connection txn, LocalAuthor a) public void addIdentity(Connection txn, Identity i) throws DbException {
throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "INSERT INTO localAuthors" String sql = "INSERT INTO localAuthors"
@@ -883,16 +883,17 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " handshakePublicKey, handshakePrivateKey, created)" + " handshakePublicKey, handshakePrivateKey, created)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getId().getBytes()); LocalAuthor local = i.getLocalAuthor();
ps.setInt(2, a.getFormatVersion()); ps.setBytes(1, local.getId().getBytes());
ps.setString(3, a.getName()); ps.setInt(2, local.getFormatVersion());
ps.setBytes(4, a.getPublicKey()); ps.setString(3, local.getName());
ps.setBytes(5, a.getPrivateKey()); ps.setBytes(4, local.getPublicKey());
if (a.getHandshakePublicKey() == null) ps.setNull(6, BINARY); ps.setBytes(5, local.getPrivateKey());
else ps.setBytes(6, a.getHandshakePublicKey()); if (i.getHandshakePublicKey() == null) ps.setNull(6, BINARY);
if (a.getHandshakePrivateKey() == null) ps.setNull(7, BINARY); else ps.setBytes(6, i.getHandshakePublicKey());
else ps.setBytes(7, a.getHandshakePrivateKey()); if (i.getHandshakePrivateKey() == null) ps.setNull(7, BINARY);
ps.setLong(8, a.getTimeCreated()); else ps.setBytes(7, i.getHandshakePrivateKey());
ps.setLong(8, i.getTimeCreated());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException(); if (affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -1248,7 +1249,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public boolean containsLocalAuthor(Connection txn, AuthorId a) public boolean containsIdentity(Connection txn, AuthorId a)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
@@ -1660,41 +1661,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public LocalAuthor getLocalAuthor(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT formatVersion, name, publicKey, privateKey,"
+ " handshakePublicKey, handshakePrivateKey, created"
+ " FROM localAuthors"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getBytes());
rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException();
int formatVersion = rs.getInt(1);
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
byte[] privateKey = rs.getBytes(4);
byte[] handshakePublicKey = rs.getBytes(5);
byte[] handshakePrivateKey = rs.getBytes(6);
long created = rs.getLong(7);
LocalAuthor localAuthor = new LocalAuthor(a, formatVersion, name,
publicKey, privateKey, handshakePublicKey,
handshakePrivateKey, created);
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
return localAuthor;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public Collection<HandshakeKeySet> getHandshakeKeys(Connection txn, public Collection<HandshakeKeySet> getHandshakeKeys(Connection txn,
TransportId t) throws DbException { TransportId t) throws DbException {
@@ -1776,30 +1742,69 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public Collection<LocalAuthor> getLocalAuthors(Connection txn) public Identity getIdentity(Connection txn, AuthorId a) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT formatVersion, name, publicKey, privateKey,"
+ " handshakePublicKey, handshakePrivateKey, created"
+ " FROM localAuthors"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getBytes());
rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException();
int formatVersion = rs.getInt(1);
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
byte[] privateKey = rs.getBytes(4);
byte[] handshakePublicKey = rs.getBytes(5);
byte[] handshakePrivateKey = rs.getBytes(6);
long created = rs.getLong(7);
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
LocalAuthor local = new LocalAuthor(a, formatVersion, name,
publicKey, privateKey);
return new Identity(local, handshakePublicKey, handshakePrivateKey,
created);
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public Collection<Identity> getIdentities(Connection txn)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT authorId, formatVersion, name, publicKey," String sql = "SELECT authorId, formatVersion, name, publicKey,"
+ " privateKey, created" + " privateKey, handshakePublicKey, handshakePrivateKey,"
+ " created"
+ " FROM localAuthors"; + " FROM localAuthors";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<LocalAuthor> authors = new ArrayList<>(); List<Identity> identities = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
AuthorId authorId = new AuthorId(rs.getBytes(1)); AuthorId authorId = new AuthorId(rs.getBytes(1));
int formatVersion = rs.getInt(2); int formatVersion = rs.getInt(2);
String name = rs.getString(3); String name = rs.getString(3);
byte[] publicKey = rs.getBytes(4); byte[] publicKey = rs.getBytes(4);
byte[] privateKey = rs.getBytes(5); byte[] privateKey = rs.getBytes(5);
long created = rs.getLong(6); byte[] handshakePublicKey = rs.getBytes(6);
authors.add(new LocalAuthor(authorId, formatVersion, name, byte[] handshakePrivateKey = rs.getBytes(7);
publicKey, privateKey, created)); long created = rs.getLong(8);
LocalAuthor local = new LocalAuthor(authorId, formatVersion,
name, publicKey, privateKey);
identities.add(new Identity(local, handshakePublicKey,
handshakePrivateKey, created));
} }
rs.close(); rs.close();
ps.close(); ps.close();
return authors; return identities;
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(rs, LOG, WARNING); tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING); tryToClose(ps, LOG, WARNING);
@@ -2958,8 +2963,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public void removeLocalAuthor(Connection txn, AuthorId a) public void removeIdentity(Connection txn, AuthorId a) throws DbException {
throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "DELETE FROM localAuthors WHERE authorId = ?"; String sql = "DELETE FROM localAuthors WHERE authorId = ?";
@@ -3176,6 +3180,27 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public void setHandshakeKeyPair(Connection txn, AuthorId local,
byte[] publicKey, byte[] privateKey) throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE localAuthors"
+ " SET handshakePublicKey = ?, handshakePrivateKey = ?"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, publicKey);
ps.setBytes(2, privateKey);
ps.setBytes(3, local.getBytes());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public void setMessageShared(Connection txn, MessageId m) public void setMessageShared(Connection txn, MessageId m)
throws DbException { throws DbException {

View File

@@ -1,12 +1,12 @@
package org.briarproject.bramble.identity; package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.ByteUtils; import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
@@ -22,12 +22,10 @@ import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
class AuthorFactoryImpl implements AuthorFactory { class AuthorFactoryImpl implements AuthorFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final Clock clock;
@Inject @Inject
AuthorFactoryImpl(CryptoComponent crypto, Clock clock) { AuthorFactoryImpl(CryptoComponent crypto) {
this.crypto = crypto; this.crypto = crypto;
this.clock = clock;
} }
@Override @Override
@@ -43,17 +41,12 @@ class AuthorFactoryImpl implements AuthorFactory {
} }
@Override @Override
public LocalAuthor createLocalAuthor(String name, byte[] publicKey, public LocalAuthor createLocalAuthor(String name) {
byte[] privateKey) { KeyPair signatureKeyPair = crypto.generateSignatureKeyPair();
return createLocalAuthor(FORMAT_VERSION, name, publicKey, privateKey); byte[] publicKey = signatureKeyPair.getPublic().getEncoded();
} byte[] privateKey = signatureKeyPair.getPrivate().getEncoded();
AuthorId id = getId(FORMAT_VERSION, name, publicKey);
@Override return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey);
public LocalAuthor createLocalAuthor(int formatVersion, String name,
byte[] publicKey, byte[] privateKey) {
AuthorId id = getId(formatVersion, name, publicKey);
return new LocalAuthor(id, formatVersion, name, publicKey, privateKey,
clock.currentTimeMillis());
} }
private AuthorId getId(int formatVersion, String name, byte[] publicKey) { private AuthorId getId(int formatVersion, String name, byte[] publicKey) {

View File

@@ -6,97 +6,164 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import java.util.Collection;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
class IdentityManagerImpl implements IdentityManager { class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(IdentityManagerImpl.class.getName()); getLogger(IdentityManagerImpl.class.getName());
private final DatabaseComponent db; private final DatabaseComponent db;
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final AuthorFactory authorFactory; private final AuthorFactory authorFactory;
private final Clock clock;
// The local author is immutable so we can cache it /**
* The user's identity, or null if no identity has been registered or
* loaded. If non-null, this identity always has handshake keys.
*/
@Nullable @Nullable
private volatile LocalAuthor cachedAuthor; private volatile Identity cachedIdentity = null;
/**
* True if {@code cachedIdentity} was registered via
* {@link #registerIdentity(Identity)} and should be stored when
* {@link #onDatabaseOpened(Transaction)} is called.
*/
private volatile boolean shouldStoreIdentity = false;
/**
* True if the handshake keys in {@code cachedIdentity} were generated
* when the identity was loaded and should be stored when
* {@link #onDatabaseOpened(Transaction)} is called.
*/
private volatile boolean shouldStoreKeys = false;
@Inject @Inject
IdentityManagerImpl(DatabaseComponent db, CryptoComponent crypto, IdentityManagerImpl(DatabaseComponent db, CryptoComponent crypto,
AuthorFactory authorFactory) { AuthorFactory authorFactory, Clock clock) {
this.db = db; this.db = db;
this.crypto = crypto; this.crypto = crypto;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
this.clock = clock;
} }
@Override @Override
public LocalAuthor createLocalAuthor(String name) { public Identity createIdentity(String name) {
long start = now(); long start = now();
KeyPair keyPair = crypto.generateSignatureKeyPair(); LocalAuthor localAuthor = authorFactory.createLocalAuthor(name);
byte[] publicKey = keyPair.getPublic().getEncoded(); KeyPair handshakeKeyPair = crypto.generateAgreementKeyPair();
byte[] privateKey = keyPair.getPrivate().getEncoded(); byte[] handshakePub = handshakeKeyPair.getPublic().getEncoded();
LocalAuthor localAuthor = authorFactory.createLocalAuthor(name, byte[] handshakePriv = handshakeKeyPair.getPrivate().getEncoded();
publicKey, privateKey); logDuration(LOG, "Creating identity", start);
logDuration(LOG, "Creating local author", start); return new Identity(localAuthor, handshakePub, handshakePriv,
return localAuthor; clock.currentTimeMillis());
} }
@Override @Override
public void registerLocalAuthor(LocalAuthor a) { public void registerIdentity(Identity i) {
cachedAuthor = a; if (!i.hasHandshakeKeyPair()) throw new IllegalArgumentException();
LOG.info("Local author registered"); cachedIdentity = i;
shouldStoreIdentity = true;
LOG.info("Identity registered");
} }
@Override @Override
public void storeLocalAuthor() throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
LocalAuthor cached = cachedAuthor; Identity cached = getCachedIdentity(txn);
if (cached == null) { if (shouldStoreIdentity) {
LOG.info("No local author to store"); // The identity was registered at startup - store it
return; db.addIdentity(txn, cached);
LOG.info("Identity stored");
} else if (shouldStoreKeys) {
// Handshake keys were generated when loading the identity -
// store them
byte[] handshakePub =
requireNonNull(cached.getHandshakePublicKey());
byte[] handshakePriv =
requireNonNull(cached.getHandshakePrivateKey());
db.setHandshakeKeyPair(txn, cached.getId(), handshakePub,
handshakePriv);
LOG.info("Handshake key pair stored");
} }
db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
LOG.info("Local author stored");
} }
@Override @Override
public LocalAuthor getLocalAuthor() throws DbException { public LocalAuthor getLocalAuthor() throws DbException {
if (cachedAuthor == null) { Identity cached = cachedIdentity;
cachedAuthor = if (cached == null)
db.transactionWithResult(true, this::loadLocalAuthor); cached = db.transactionWithResult(true, this::getCachedIdentity);
LOG.info("Local author loaded"); return cached.getLocalAuthor();
}
LocalAuthor cached = cachedAuthor;
if (cached == null) throw new AssertionError();
return cached;
} }
@Override @Override
public LocalAuthor getLocalAuthor(Transaction txn) throws DbException { public LocalAuthor getLocalAuthor(Transaction txn) throws DbException {
if (cachedAuthor == null) { return getCachedIdentity(txn).getLocalAuthor();
cachedAuthor = loadLocalAuthor(txn); }
LOG.info("Local author loaded");
} @Override
LocalAuthor cached = cachedAuthor; public byte[][] getHandshakeKeys(Transaction txn) throws DbException {
if (cached == null) throw new AssertionError(); Identity cached = getCachedIdentity(txn);
return new byte[][] {
cached.getHandshakePublicKey(),
cached.getHandshakePrivateKey()
};
}
/**
* Loads the identity if necessary and returns it. If
* {@code cachedIdentity} was not already set by calling
* {@link #registerIdentity(Identity)}, this method sets it. If
* {@code cachedIdentity} was already set, either by calling
* {@link #registerIdentity(Identity)} or by a previous call to this
* method, then this method returns the cached identity without hitting
* the database.
*/
private Identity getCachedIdentity(Transaction txn) throws DbException {
Identity cached = cachedIdentity;
if (cached == null)
cachedIdentity = cached = loadIdentityWithKeyPair(txn);
return cached; return cached;
} }
private LocalAuthor loadLocalAuthor(Transaction txn) throws DbException { /**
return db.getLocalAuthors(txn).iterator().next(); * Loads and returns the identity, generating a handshake key pair if
* necessary and setting {@code shouldStoreKeys} if a handshake key pair
* was generated.
*/
private Identity loadIdentityWithKeyPair(Transaction txn)
throws DbException {
Collection<Identity> identities = db.getIdentities(txn);
if (identities.size() != 1) throw new DbException();
Identity i = identities.iterator().next();
LOG.info("Identity loaded");
if (i.hasHandshakeKeyPair()) return i;
KeyPair handshakeKeyPair = crypto.generateAgreementKeyPair();
byte[] handshakePub = handshakeKeyPair.getPublic().getEncoded();
byte[] handshakePriv = handshakeKeyPair.getPrivate().getEncoded();
LOG.info("Handshake key pair generated");
shouldStoreKeys = true;
return new Identity(i.getLocalAuthor(), handshakePub, handshakePriv,
i.getTimeCreated());
} }
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -24,8 +25,9 @@ public class IdentityModule {
@Provides @Provides
@Singleton @Singleton
IdentityManager provideIdentityManager( IdentityManager provideIdentityManager(LifecycleManager lifecycleManager,
IdentityManagerImpl identityManager) { IdentityManagerImpl identityManager) {
lifecycleManager.registerOpenDatabaseHook(identityManager);
return identityManager; return identityManager;
} }
} }

View File

@@ -7,13 +7,11 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.Service; import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException; import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@@ -28,6 +26,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.FINE; import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
@@ -49,14 +48,13 @@ import static org.briarproject.bramble.util.LogUtils.now;
class LifecycleManagerImpl implements LifecycleManager, MigrationListener { class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(LifecycleManagerImpl.class.getName()); getLogger(LifecycleManagerImpl.class.getName());
private final DatabaseComponent db; private final DatabaseComponent db;
private final EventBus eventBus; private final EventBus eventBus;
private final List<Service> services; private final List<Service> services;
private final List<Client> clients; private final List<OpenDatabaseHook> openDatabaseHooks;
private final List<ExecutorService> executors; private final List<ExecutorService> executors;
private final IdentityManager identityManager;
private final Semaphore startStopSemaphore = new Semaphore(1); private final Semaphore startStopSemaphore = new Semaphore(1);
private final CountDownLatch dbLatch = new CountDownLatch(1); private final CountDownLatch dbLatch = new CountDownLatch(1);
private final CountDownLatch startupLatch = new CountDownLatch(1); private final CountDownLatch startupLatch = new CountDownLatch(1);
@@ -65,13 +63,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private volatile LifecycleState state = STARTING; private volatile LifecycleState state = STARTING;
@Inject @Inject
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus, LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus) {
IdentityManager identityManager) {
this.db = db; this.db = db;
this.eventBus = eventBus; this.eventBus = eventBus;
this.identityManager = identityManager;
services = new CopyOnWriteArrayList<>(); services = new CopyOnWriteArrayList<>();
clients = new CopyOnWriteArrayList<>(); openDatabaseHooks = new CopyOnWriteArrayList<>();
executors = new CopyOnWriteArrayList<>(); executors = new CopyOnWriteArrayList<>();
} }
@@ -83,10 +79,12 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
} }
@Override @Override
public void registerClient(Client c) { public void registerOpenDatabaseHook(OpenDatabaseHook hook) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO)) {
LOG.info("Registering client " + c.getClass().getSimpleName()); LOG.info("Registering open database hook "
clients.add(c); + hook.getClass().getSimpleName());
}
openDatabaseHooks.add(hook);
} }
@Override @Override
@@ -102,28 +100,28 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
return ALREADY_RUNNING; return ALREADY_RUNNING;
} }
try { try {
LOG.info("Starting services"); LOG.info("Opening database");
long start = now(); long start = now();
boolean reopened = db.open(dbKey, this); boolean reopened = db.open(dbKey, this);
if (reopened) logDuration(LOG, "Reopening database", start); if (reopened) logDuration(LOG, "Reopening database", start);
else logDuration(LOG, "Creating database", start); else logDuration(LOG, "Creating database", start);
identityManager.storeLocalAuthor();
db.transaction(false, txn -> {
for (OpenDatabaseHook hook : openDatabaseHooks) {
long start1 = now();
hook.onDatabaseOpened(txn);
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Calling open database hook "
+ hook.getClass().getSimpleName(), start1);
}
}
});
LOG.info("Starting services");
state = STARTING_SERVICES; state = STARTING_SERVICES;
dbLatch.countDown(); dbLatch.countDown();
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES)); eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
db.transaction(false, txn -> {
for (Client c : clients) {
long start1 = now();
c.createLocalState(txn);
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Starting client "
+ c.getClass().getSimpleName(), start1);
}
}
});
for (Service s : services) { for (Service s : services) {
start = now(); start = now();
s.startService(); s.startService();

View File

@@ -48,7 +48,7 @@ public class PropertiesModule {
ValidationManager validationManager, ContactManager contactManager, ValidationManager validationManager, ContactManager contactManager,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
TransportPropertyManagerImpl transportPropertyManager) { TransportPropertyManagerImpl transportPropertyManager) {
lifecycleManager.registerClient(transportPropertyManager); lifecycleManager.registerOpenDatabaseHook(transportPropertyManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
transportPropertyManager); transportPropertyManager);
contactManager.registerContactHook(transportPropertyManager); contactManager.registerContactHook(transportPropertyManager);

View File

@@ -13,11 +13,11 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager; import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -40,7 +40,8 @@ import javax.inject.Inject;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class TransportPropertyManagerImpl implements TransportPropertyManager, class TransportPropertyManagerImpl implements TransportPropertyManager,
Client, ContactHook, ClientVersioningHook, IncomingMessageHook { OpenDatabaseHook, ContactHook, ClientVersioningHook,
IncomingMessageHook {
private final DatabaseComponent db; private final DatabaseComponent db;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
@@ -67,7 +68,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
if (db.containsGroup(txn, localGroup.getId())) return; if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup); db.addGroup(txn, localGroup);
// Set things up for any pre-existing contacts // Set things up for any pre-existing contacts

View File

@@ -12,10 +12,10 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.Service; import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException; import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -53,8 +53,8 @@ import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION; import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
@NotNullByDefault @NotNullByDefault
class ClientVersioningManagerImpl implements ClientVersioningManager, Client, class ClientVersioningManagerImpl implements ClientVersioningManager,
Service, ContactHook, IncomingMessageHook { Service, OpenDatabaseHook, ContactHook, IncomingMessageHook {
private final DatabaseComponent db; private final DatabaseComponent db;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
@@ -124,7 +124,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
if (db.containsGroup(txn, localGroup.getId())) return; if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup); db.addGroup(txn, localGroup);
// Set things up for any pre-existing contacts // Set things up for any pre-existing contacts

View File

@@ -34,7 +34,7 @@ public class VersioningModule {
ClientVersioningManagerImpl clientVersioningManager, ClientVersioningManagerImpl clientVersioningManager,
LifecycleManager lifecycleManager, ContactManager contactManager, LifecycleManager lifecycleManager, ContactManager contactManager,
ValidationManager validationManager) { ValidationManager validationManager) {
lifecycleManager.registerClient(clientVersioningManager); lifecycleManager.registerOpenDatabaseHook(clientVersioningManager);
lifecycleManager.registerService(clientVersioningManager); lifecycleManager.registerService(clientVersioningManager);
contactManager.registerContactHook(clientVersioningManager); contactManager.registerContactHook(clientVersioningManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.account;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
@@ -24,7 +25,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
@@ -47,7 +48,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
private final String encryptedKeyHex = toHexString(encryptedKey); private final String encryptedKeyHex = toHexString(encryptedKey);
private final byte[] newEncryptedKey = getRandomBytes(123); private final byte[] newEncryptedKey = getRandomBytes(123);
private final String newEncryptedKeyHex = toHexString(newEncryptedKey); private final String newEncryptedKeyHex = toHexString(newEncryptedKey);
private final LocalAuthor localAuthor = getLocalAuthor(); private final Identity identity = getIdentity();
private final LocalAuthor localAuthor = identity.getLocalAuthor();
private final String authorName = localAuthor.getName(); private final String authorName = localAuthor.getName();
private final String password = getRandomString(10); private final String password = getRandomString(10);
private final String newPassword = getRandomString(10); private final String newPassword = getRandomString(10);
@@ -251,9 +253,9 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testCreateAccountStoresDbKey() throws Exception { public void testCreateAccountStoresDbKey() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(identityManager).createLocalAuthor(authorName); oneOf(identityManager).createIdentity(authorName);
will(returnValue(localAuthor)); will(returnValue(identity));
oneOf(identityManager).registerLocalAuthor(localAuthor); oneOf(identityManager).registerIdentity(identity);
oneOf(crypto).generateSecretKey(); oneOf(crypto).generateSecretKey();
will(returnValue(key)); will(returnValue(key));
oneOf(crypto).encryptWithPassword(key.getBytes(), password); oneOf(crypto).encryptWithPassword(key.getBytes(), password);

View File

@@ -11,16 +11,17 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.NoSuchGroupException; import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException; import org.briarproject.bramble.api.db.NoSuchIdentityException;
import org.briarproject.bramble.api.db.NoSuchMessageException; import org.briarproject.bramble.api.db.NoSuchMessageException;
import org.briarproject.bramble.api.db.NoSuchPendingContactException; import org.briarproject.bramble.api.db.NoSuchPendingContactException;
import org.briarproject.bramble.api.db.NoSuchTransportException; import org.briarproject.bramble.api.db.NoSuchTransportException;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent; import org.briarproject.bramble.api.identity.event.IdentityAddedEvent;
import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent; import org.briarproject.bramble.api.identity.event.IdentityRemovedEvent;
import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
@@ -65,6 +66,7 @@ import java.util.concurrent.atomic.AtomicReference;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
@@ -77,8 +79,9 @@ import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getClientId; import static org.briarproject.bramble.test.TestUtils.getClientId;
import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTransportId; import static org.briarproject.bramble.test.TestUtils.getTransportId;
@@ -104,6 +107,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
private final GroupId groupId; private final GroupId groupId;
private final Group group; private final Group group;
private final Author author; private final Author author;
private final Identity identity;
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
private final String alias; private final String alias;
private final Message message, message1; private final Message message, message1;
@@ -122,7 +126,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
group = getGroup(clientId, majorVersion); group = getGroup(clientId, majorVersion);
groupId = group.getId(); groupId = group.getId();
author = getAuthor(); author = getAuthor();
localAuthor = getLocalAuthor(); identity = getIdentity();
localAuthor = identity.getLocalAuthor();
message = getMessage(groupId); message = getMessage(groupId);
message1 = getMessage(groupId); message1 = getMessage(groupId);
messageId = message.getId(); messageId = message.getId();
@@ -157,15 +162,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
// registerLocalAuthor() // addIdentity()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId()); oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).addLocalAuthor(txn, localAuthor); oneOf(database).addIdentity(txn, identity);
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class))); oneOf(eventBus).broadcast(with(any(IdentityAddedEvent.class)));
// addContact() // addContact()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId()); oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, author.getId()); oneOf(database).containsIdentity(txn, author.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).containsContact(txn, author.getId(), oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId()); localAuthor.getId());
@@ -201,11 +206,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
will(returnValue(true)); will(returnValue(true));
oneOf(database).removeContact(txn, contactId); oneOf(database).removeContact(txn, contactId);
oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class))); oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class)));
// removeLocalAuthor() // removeIdentity()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId()); oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).removeLocalAuthor(txn, localAuthor.getId()); oneOf(database).removeIdentity(txn, localAuthor.getId());
oneOf(eventBus).broadcast(with(any(LocalAuthorRemovedEvent.class))); oneOf(eventBus).broadcast(with(any(IdentityRemovedEvent.class)));
// endTransaction() // endTransaction()
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
// close() // close()
@@ -216,7 +221,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
assertFalse(db.open(key, null)); assertFalse(db.open(key, null));
db.transaction(false, transaction -> { db.transaction(false, transaction -> {
db.addLocalAuthor(transaction, localAuthor); db.addIdentity(transaction, identity);
assertEquals(contactId, db.addContact(transaction, author, assertEquals(contactId, db.addContact(transaction, author,
localAuthor.getId(), true)); localAuthor.getId(), true));
assertEquals(singletonList(contact), assertEquals(singletonList(contact),
@@ -227,7 +232,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
db.getGroups(transaction, clientId, majorVersion)); db.getGroups(transaction, clientId, majorVersion));
db.removeGroup(transaction, group); db.removeGroup(transaction, group);
db.removeContact(transaction, contactId); db.removeContact(transaction, contactId);
db.removeLocalAuthor(transaction, localAuthor.getId()); db.removeIdentity(transaction, localAuthor.getId());
}); });
db.close(); db.close();
} }
@@ -432,16 +437,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
@Test @Test
public void testVariousMethodsThrowExceptionIfLocalAuthorIsMissing() public void testVariousMethodsThrowExceptionIfIdentityIsMissing()
throws Exception { throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the pseudonym is in the DB (which it's not) // Check whether the identity is in the DB (which it's not)
exactly(3).of(database).startTransaction(); exactly(4).of(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
exactly(3).of(database).containsLocalAuthor(txn, exactly(4).of(database).containsIdentity(txn, localAuthor.getId());
localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
exactly(3).of(database).abortTransaction(txn); exactly(4).of(database).abortTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, eventBus, DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager); eventExecutor, shutdownManager);
@@ -451,23 +455,34 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
db.addContact(transaction, author, localAuthor.getId(), db.addContact(transaction, author, localAuthor.getId(),
true)); true));
fail(); fail();
} catch (NoSuchLocalAuthorException expected) { } catch (NoSuchIdentityException expected) {
// Expected // Expected
} }
try { try {
db.transaction(false, transaction -> db.transaction(false, transaction ->
db.getLocalAuthor(transaction, localAuthor.getId())); db.getIdentity(transaction, localAuthor.getId()));
fail(); fail();
} catch (NoSuchLocalAuthorException expected) { } catch (NoSuchIdentityException expected) {
// Expected // Expected
} }
try { try {
db.transaction(false, transaction -> db.transaction(false, transaction ->
db.removeLocalAuthor(transaction, localAuthor.getId())); db.removeIdentity(transaction, localAuthor.getId()));
fail(); fail();
} catch (NoSuchLocalAuthorException expected) { } catch (NoSuchIdentityException expected) {
// Expected
}
try {
byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
byte[] privateKey = getRandomBytes(123);
db.transaction(false, transaction ->
db.setHandshakeKeyPair(transaction, localAuthor.getId(),
publicKey, privateKey));
fail();
} catch (NoSuchIdentityException expected) {
// Expected // Expected
} }
} }
@@ -1403,10 +1418,10 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthor.getId()); oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
// Contact is a local identity // Contact is a local identity
oneOf(database).containsLocalAuthor(txn, author.getId()); oneOf(database).containsIdentity(txn, author.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).abortTransaction(txn); oneOf(database).abortTransaction(txn);
}}); }});
@@ -1429,9 +1444,9 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthor.getId()); oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, author.getId()); oneOf(database).containsIdentity(txn, author.getId());
will(returnValue(false)); will(returnValue(false));
// Contact already exists for this local identity // Contact already exists for this local identity
oneOf(database).containsContact(txn, author.getId(), oneOf(database).containsContact(txn, author.getId(),
@@ -1454,7 +1469,6 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
@Test @Test
@SuppressWarnings("unchecked")
public void testMessageDependencies() throws Exception { public void testMessageDependencies() throws Exception {
int shutdownHandle = 12345; int shutdownHandle = 12345;
MessageId messageId2 = new MessageId(getRandomId()); MessageId messageId2 = new MessageId(getRandomId());

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
@@ -37,7 +38,7 @@ import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERE
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
@@ -161,11 +162,11 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
} }
@Test @Test
public void testContainsLocalAuthor() throws Exception { public void testContainsIdentity() throws Exception {
String name = "containsLocalAuthor(T, AuthorId)"; String name = "containsIdentity(T, AuthorId)";
benchmark(name, db -> { benchmark(name, db -> {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
db.containsLocalAuthor(txn, localAuthor.getId()); db.containsIdentity(txn, localAuthor.getId());
db.commitTransaction(txn); db.commitTransaction(txn);
}); });
} }
@@ -295,21 +296,21 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
} }
@Test @Test
public void testGetLocalAuthor() throws Exception { public void testGetIdentity() throws Exception {
String name = "getLocalAuthor(T, AuthorId)"; String name = "getIdentity(T, AuthorId)";
benchmark(name, db -> { benchmark(name, db -> {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
db.getLocalAuthor(txn, localAuthor.getId()); db.getIdentity(txn, localAuthor.getId());
db.commitTransaction(txn); db.commitTransaction(txn);
}); });
} }
@Test @Test
public void testGetLocalAuthors() throws Exception { public void testGetIdentities() throws Exception {
String name = "getLocalAuthors(T)"; String name = "getIdentities(T)";
benchmark(name, db -> { benchmark(name, db -> {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
db.getLocalAuthors(txn); db.getIdentities(txn);
db.commitTransaction(txn); db.commitTransaction(txn);
}); });
} }
@@ -531,7 +532,8 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
} }
void populateDatabase(Database<Connection> db) throws DbException { void populateDatabase(Database<Connection> db) throws DbException {
localAuthor = getLocalAuthor(); Identity identity = getIdentity();
localAuthor = identity.getLocalAuthor();
clientIds = new ArrayList<>(); clientIds = new ArrayList<>();
contacts = new ArrayList<>(); contacts = new ArrayList<>();
groups = new ArrayList<>(); groups = new ArrayList<>();
@@ -543,7 +545,7 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
for (int i = 0; i < CLIENTS; i++) clientIds.add(getClientId()); for (int i = 0; i < CLIENTS; i++) clientIds.add(getClientId());
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
for (int i = 0; i < CONTACTS; i++) { for (int i = 0; i < CONTACTS; i++) {
ContactId c = db.addContact(txn, getAuthor(), localAuthor.getId(), ContactId c = db.addContact(txn, getAuthor(), localAuthor.getId(),
random.nextBoolean()); random.nextBoolean());

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MessageDeletedException; import org.briarproject.bramble.api.db.MessageDeletedException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
@@ -57,6 +58,7 @@ import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.contact.PendingContactState.FAILED; import static org.briarproject.bramble.api.contact.PendingContactState.FAILED;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.db.Metadata.REMOVE; import static org.briarproject.bramble.api.db.Metadata.REMOVE;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
@@ -73,9 +75,10 @@ import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getClientId; import static org.briarproject.bramble.test.TestUtils.getClientId;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getPendingContact; import static org.briarproject.bramble.test.TestUtils.getPendingContact;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
@@ -103,6 +106,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private final int majorVersion; private final int majorVersion;
private final Group group; private final Group group;
private final Author author; private final Author author;
private final Identity identity;
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
private final Message message; private final Message message;
private final MessageId messageId; private final MessageId messageId;
@@ -119,7 +123,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
group = getGroup(clientId, majorVersion); group = getGroup(clientId, majorVersion);
groupId = group.getId(); groupId = group.getId();
author = getAuthor(); author = getAuthor();
localAuthor = getLocalAuthor(); identity = getIdentity();
localAuthor = identity.getLocalAuthor();
message = getMessage(groupId); message = getMessage(groupId);
messageId = message.getId(); messageId = message.getId();
transportId = getTransportId(); transportId = getTransportId();
@@ -145,7 +150,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
assertFalse(db.containsContact(txn, contactId)); assertFalse(db.containsContact(txn, contactId));
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
assertTrue(db.containsContact(txn, contactId)); assertTrue(db.containsContact(txn, contactId));
@@ -208,7 +213,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -239,7 +244,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared but unvalidated message // Add a contact, a shared group and a shared but unvalidated message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -284,7 +289,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, an invisible group and a shared message // Add a contact, an invisible group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -335,7 +340,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and an unshared message // Add a contact, a shared group and an unshared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -366,7 +371,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -393,7 +398,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact and a visible group // Add a contact and a visible group
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -434,7 +439,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -566,7 +571,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact and a shared group // Add a contact and a shared group
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -586,7 +591,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact // Add a contact
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
@@ -604,7 +609,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, an invisible group and a message // Add a contact, an invisible group and a message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -623,7 +628,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact and a group // Add a contact and a group
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -675,7 +680,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getTransportKeys(txn, transportId)); assertEquals(emptyList(), db.getTransportKeys(txn, transportId));
// Add the contact, the transport and the transport keys // Add the contact, the transport and the transport keys
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
@@ -776,7 +781,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getHandshakeKeys(txn, transportId)); assertEquals(emptyList(), db.getHandshakeKeys(txn, transportId));
// Add the contact, the transport and the handshake keys // Add the contact, the transport and the handshake keys
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
@@ -929,7 +934,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add the contact, transport and transport keys // Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
@@ -973,7 +978,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add the contact, transport and handshake keys // Add the contact, transport and handshake keys
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
@@ -1020,7 +1025,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add the contact, transport and transport keys // Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
@@ -1067,7 +1072,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add the contact, transport and handshake keys // Add the contact, transport and handshake keys
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
@@ -1109,14 +1114,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a local author - no contacts should be associated // Add an identity for a local author - no contacts should be
db.addLocalAuthor(txn, localAuthor); // associated
db.addIdentity(txn, identity);
// Add a contact associated with the local author // Add a contact associated with the local author
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
// Ensure contact is returned from database by Author ID // Ensure contact is returned from database by author ID
Collection<Contact> contacts = Collection<Contact> contacts =
db.getContactsByAuthorId(txn, author.getId()); db.getContactsByAuthorId(txn, author.getId());
assertEquals(1, contacts.size()); assertEquals(1, contacts.size());
@@ -1136,8 +1142,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a local author - no contacts should be associated // Add an identity for a local author - no contacts should be
db.addLocalAuthor(txn, localAuthor); // associated
db.addIdentity(txn, identity);
Collection<ContactId> contacts = Collection<ContactId> contacts =
db.getContacts(txn, localAuthor.getId()); db.getContacts(txn, localAuthor.getId());
assertEquals(emptyList(), contacts); assertEquals(emptyList(), contacts);
@@ -1148,8 +1155,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
contacts = db.getContacts(txn, localAuthor.getId()); contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(singletonList(contactId), contacts); assertEquals(singletonList(contactId), contacts);
// Remove the local author - the contact should be removed // Remove the identity - the contact should be removed
db.removeLocalAuthor(txn, localAuthor.getId()); db.removeIdentity(txn, localAuthor.getId());
contacts = db.getContacts(txn, localAuthor.getId()); contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(emptyList(), contacts); assertEquals(emptyList(), contacts);
assertFalse(db.containsContact(txn, contactId)); assertFalse(db.containsContact(txn, contactId));
@@ -1164,7 +1171,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact - initially there should be no offered messages // Add a contact - initially there should be no offered messages
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(0, db.countOfferedMessages(txn, contactId)); assertEquals(0, db.countOfferedMessages(txn, contactId));
@@ -1748,7 +1755,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -1850,14 +1857,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testDifferentLocalAuthorsCanHaveTheSameContact() public void testDifferentLocalAuthorsCanHaveTheSameContact()
throws Exception { throws Exception {
LocalAuthor localAuthor1 = getLocalAuthor(); Identity identity1 = getIdentity();
LocalAuthor localAuthor1 = identity1.getLocalAuthor();
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add two local authors // Add identities for two local authors
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
db.addLocalAuthor(txn, localAuthor1); db.addIdentity(txn, identity1);
// Add the same contact for each local author // Add the same contact for each local author
ContactId contactId = ContactId contactId =
@@ -1881,7 +1889,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -1935,7 +1943,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact // Add a contact
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
@@ -1992,7 +2000,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a group and a message // Add a contact, a group and a message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -2076,7 +2084,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -2121,7 +2129,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addIdentity(txn, identity);
assertEquals(contactId, assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true)); db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -2237,6 +2245,30 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.close(); db.close();
} }
@Test
public void testSetHandshakeKeyPair() throws Exception {
Identity withoutKeys =
new Identity(localAuthor, null, null, identity.getTimeCreated());
assertFalse(withoutKeys.hasHandshakeKeyPair());
byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
byte[] privateKey = getRandomBytes(123);
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
db.addIdentity(txn, withoutKeys);
Identity retrieved = db.getIdentity(txn, localAuthor.getId());
assertFalse(retrieved.hasHandshakeKeyPair());
db.setHandshakeKeyPair(txn, localAuthor.getId(), publicKey, privateKey);
retrieved = db.getIdentity(txn, localAuthor.getId());
assertTrue(retrieved.hasHandshakeKeyPair());
assertArrayEquals(publicKey, retrieved.getHandshakePublicKey());
assertArrayEquals(privateKey, retrieved.getHandshakePrivateKey());
db.commitTransaction(txn);
db.close();
}
private Database<Connection> open(boolean resume) throws Exception { private Database<Connection> open(boolean resume) throws Exception {
return open(resume, new TestMessageFactory(), new SystemClock()); return open(resume, new TestMessageFactory(), new SystemClock());
} }

View File

@@ -8,18 +8,17 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations; import org.briarproject.bramble.test.DbExpectations;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.Collection; import static java.util.Collections.singletonList;
import java.util.Collections; import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class IdentityManagerImplTest extends BrambleMockTestCase { public class IdentityManagerImplTest extends BrambleMockTestCase {
@@ -28,67 +27,100 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final AuthorFactory authorFactory = private final AuthorFactory authorFactory =
context.mock(AuthorFactory.class); context.mock(AuthorFactory.class);
private final PublicKey publicKey = context.mock(PublicKey.class); private final Clock clock = context.mock(Clock.class);
private final PrivateKey privateKey = context.mock(PrivateKey.class); private final PublicKey handshakePublicKey = context.mock(PublicKey.class);
private final PrivateKey handshakePrivateKey =
context.mock(PrivateKey.class);
private final Transaction txn = new Transaction(null, false); private final Transaction txn = new Transaction(null, false);
private final LocalAuthor localAuthor = getLocalAuthor(); private final Identity identityWithKeys = getIdentity();
private final Collection<LocalAuthor> localAuthors = private final LocalAuthor localAuthor = identityWithKeys.getLocalAuthor();
Collections.singletonList(localAuthor); private final Identity identityWithoutKeys = new Identity(localAuthor,
private final String authorName = localAuthor.getName(); null, null, identityWithKeys.getTimeCreated());
private final KeyPair keyPair = new KeyPair(publicKey, privateKey); private final KeyPair handshakeKeyPair =
private final byte[] publicKeyBytes = localAuthor.getPublicKey(); new KeyPair(handshakePublicKey, handshakePrivateKey);
private final byte[] privateKeyBytes = localAuthor.getPrivateKey(); private final byte[] handshakePublicKeyBytes =
private IdentityManager identityManager; identityWithKeys.getHandshakePublicKey();
private final byte[] handshakePrivateKeyBytes =
identityWithKeys.getHandshakePrivateKey();
private IdentityManagerImpl identityManager;
@Before @Before
public void setUp() { public void setUp() {
identityManager = new IdentityManagerImpl(db, crypto, authorFactory); identityManager =
new IdentityManagerImpl(db, crypto, authorFactory, clock);
} }
@Test @Test
public void testCreateLocalAuthor() { public void testOpenDatabaseIdentityRegistered() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).generateSignatureKeyPair(); oneOf(db).addIdentity(txn, identityWithKeys);
will(returnValue(keyPair));
oneOf(publicKey).getEncoded();
will(returnValue(publicKeyBytes));
oneOf(privateKey).getEncoded();
will(returnValue(privateKeyBytes));
oneOf(authorFactory).createLocalAuthor(authorName,
publicKeyBytes, privateKeyBytes);
will(returnValue(localAuthor));
}}); }});
assertEquals(localAuthor, identityManager.registerIdentity(identityWithKeys);
identityManager.createLocalAuthor(authorName)); identityManager.onDatabaseOpened(txn);
} }
@Test @Test
public void testRegisterAndStoreLocalAuthor() throws Exception { public void testOpenDatabaseHandshakeKeysGenerated() throws Exception {
context.checking(new DbExpectations() {{ context.checking(new Expectations() {{
oneOf(db).transaction(with(false), withDbRunnable(txn)); oneOf(db).getIdentities(txn);
oneOf(db).addLocalAuthor(txn, localAuthor); will(returnValue(singletonList(identityWithoutKeys)));
oneOf(crypto).generateAgreementKeyPair();
will(returnValue(handshakeKeyPair));
oneOf(handshakePublicKey).getEncoded();
will(returnValue(handshakePublicKeyBytes));
oneOf(handshakePrivateKey).getEncoded();
will(returnValue(handshakePrivateKeyBytes));
oneOf(db).setHandshakeKeyPair(txn, localAuthor.getId(),
handshakePublicKeyBytes, handshakePrivateKeyBytes);
}}); }});
identityManager.registerLocalAuthor(localAuthor); identityManager.onDatabaseOpened(txn);
}
@Test
public void testOpenDatabaseNoHandshakeKeysGenerated() throws Exception {
context.checking(new Expectations() {{
oneOf(db).getIdentities(txn);
will(returnValue(singletonList(identityWithKeys)));
}});
identityManager.onDatabaseOpened(txn);
}
@Test
public void testGetLocalAuthorIdentityRegistered() throws DbException {
identityManager.registerIdentity(identityWithKeys);
assertEquals(localAuthor, identityManager.getLocalAuthor()); assertEquals(localAuthor, identityManager.getLocalAuthor());
identityManager.storeLocalAuthor();
} }
@Test @Test
public void testGetLocalAuthor() throws Exception { public void testGetLocalAuthorHandshakeKeysGenerated() throws Exception {
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getLocalAuthors(txn); oneOf(db).getIdentities(txn);
will(returnValue(localAuthors)); will(returnValue(singletonList(identityWithoutKeys)));
oneOf(crypto).generateAgreementKeyPair();
will(returnValue(handshakeKeyPair));
oneOf(handshakePublicKey).getEncoded();
will(returnValue(handshakePublicKeyBytes));
oneOf(handshakePrivateKey).getEncoded();
will(returnValue(handshakePrivateKeyBytes));
}}); }});
assertEquals(localAuthor, identityManager.getLocalAuthor()); assertEquals(localAuthor, identityManager.getLocalAuthor());
} }
@Test @Test
public void testGetCachedLocalAuthor() throws DbException { public void testGetLocalAuthorNoHandshakeKeysGenerated() throws Exception {
identityManager.registerLocalAuthor(localAuthor); context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getIdentities(txn);
will(returnValue(singletonList(identityWithKeys)));
}});
assertEquals(localAuthor, identityManager.getLocalAuthor()); assertEquals(localAuthor, identityManager.getLocalAuthor());
} }

View File

@@ -0,0 +1,53 @@
package org.briarproject.bramble.lifecycle;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicBoolean;
import static junit.framework.TestCase.assertTrue;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertEquals;
public class LifecycleManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final EventBus eventBus = context.mock(EventBus.class);
private final SecretKey dbKey = getSecretKey();
private LifecycleManagerImpl lifecycleManager;
@Before
public void setUp() {
lifecycleManager = new LifecycleManagerImpl(db, eventBus);
}
@Test
public void testOpenDatabaseHooksAreCalledAtStartup() throws Exception {
Transaction txn = new Transaction(null, false);
AtomicBoolean called = new AtomicBoolean(false);
OpenDatabaseHook hook = transaction -> called.set(true);
context.checking(new DbExpectations() {{
oneOf(db).open(dbKey, lifecycleManager);
will(returnValue(false));
oneOf(db).transaction(with(false), withDbRunnable(txn));
allowing(eventBus).broadcast(with(any(LifecycleEvent.class)));
}});
lifecycleManager.registerOpenDatabaseHook(hook);
assertEquals(SUCCESS, lifecycleManager.startServices(dbKey));
assertTrue(called.get());
}
}

View File

@@ -115,7 +115,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
1, true, true); 1, true, true);
TransportPropertyManagerImpl t = createInstance(); TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn); t.onDatabaseOpened(txn);
} }
@Test @Test
@@ -129,7 +129,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
}}); }});
TransportPropertyManagerImpl t = createInstance(); TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn); t.onDatabaseOpened(txn);
} }
@Test @Test

View File

@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.Service; import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -32,7 +31,7 @@ public class TestLifecycleModule {
} }
@Override @Override
public void registerClient(Client c) { public void registerOpenDatabaseHook(OpenDatabaseHook hook) {
} }
@Override @Override

View File

@@ -83,7 +83,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
expectAddingContact(); expectAddingContact();
ClientVersioningManagerImpl c = createInstance(); ClientVersioningManagerImpl c = createInstance();
c.createLocalState(txn); c.onDatabaseOpened(txn);
} }
@Test @Test
@@ -95,7 +95,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
}}); }});
ClientVersioningManagerImpl c = createInstance(); ClientVersioningManagerImpl c = createInstance();
c.createLocalState(txn); c.onDatabaseOpened(txn);
} }
@Test @Test

View File

@@ -226,7 +226,7 @@ public class AppModule {
@Singleton @Singleton
RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager, RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager,
RecentEmojiImpl recentEmoji) { RecentEmojiImpl recentEmoji) {
lifecycleManager.registerClient(recentEmoji); lifecycleManager.registerOpenDatabaseHook(recentEmoji);
return recentEmoji; return recentEmoji;
} }
} }

View File

@@ -8,11 +8,11 @@ import com.vanniktech.emoji.emoji.Emoji;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager; import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
@@ -30,7 +30,7 @@ import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
class RecentEmojiImpl implements RecentEmoji, Client { class RecentEmojiImpl implements RecentEmoji, OpenDatabaseHook {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(RecentEmojiImpl.class.getName()); Logger.getLogger(RecentEmojiImpl.class.getName());
@@ -72,7 +72,7 @@ class RecentEmojiImpl implements RecentEmoji, Client {
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
Settings settings = Settings settings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE); settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
String serialized = settings.get(EMOJI_LRU_PREFERENCE); String serialized = settings.get(EMOJI_LRU_PREFERENCE);

View File

@@ -124,6 +124,12 @@ public interface BlogManager {
void registerRemoveBlogHook(RemoveBlogHook hook); void registerRemoveBlogHook(RemoveBlogHook hook);
interface RemoveBlogHook { interface RemoveBlogHook {
/**
* Called when a blog is being removed.
*
* @param txn A read-write transaction
* @param b The blog that is being removed
*/
void removingBlog(Transaction txn, Blog b) throws DbException; void removingBlog(Transaction txn, Blog b) throws DbException;
} }

View File

@@ -100,6 +100,12 @@ public interface ForumManager {
void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
interface RemoveForumHook { interface RemoveForumHook {
/**
* Called when a forum is being removed.
*
* @param txn A read-write transaction
* @param f The forum that is being removed
*/
void removingForum(Transaction txn, Forum f) throws DbException; void removingForum(Transaction txn, Forum f) throws DbException;
} }
} }

View File

@@ -140,9 +140,22 @@ public interface PrivateGroupManager {
@NotNullByDefault @NotNullByDefault
interface PrivateGroupHook { interface PrivateGroupHook {
/**
* Called when a member is being added to a private group.
*
* @param txn A read-write transaction
* @param g The ID of the private group
* @param a The member that is being added
*/
void addingMember(Transaction txn, GroupId g, Author a) void addingMember(Transaction txn, GroupId g, Author a)
throws DbException; throws DbException;
/**
* Called when a private group is being removed.
*
* @param txn A read-write transaction
* @param g The ID of the private group that is being removed
*/
void removingGroup(Transaction txn, GroupId g) throws DbException; void removingGroup(Transaction txn, GroupId g) throws DbException;
} }

View File

@@ -18,8 +18,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo; import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
@@ -68,7 +68,7 @@ import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
@NotNullByDefault @NotNullByDefault
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
ContactHook, Client { OpenDatabaseHook, ContactHook {
private final ContactManager contactManager; private final ContactManager contactManager;
private final IdentityManager identityManager; private final IdentityManager identityManager;
@@ -90,7 +90,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
// Create our personal blog if necessary // Create our personal blog if necessary
LocalAuthor a = identityManager.getLocalAuthor(txn); LocalAuthor a = identityManager.getLocalAuthor(txn);
Blog b = blogFactory.createBlog(a); Blog b = blogFactory.createBlog(a);

View File

@@ -36,7 +36,7 @@ public class BlogModule {
BlogManager provideBlogManager(BlogManagerImpl blogManager, BlogManager provideBlogManager(BlogManagerImpl blogManager,
LifecycleManager lifecycleManager, ContactManager contactManager, LifecycleManager lifecycleManager, ContactManager contactManager,
ValidationManager validationManager) { ValidationManager validationManager) {
lifecycleManager.registerClient(blogManager); lifecycleManager.registerOpenDatabaseHook(blogManager);
contactManager.registerContactHook(blogManager); contactManager.registerContactHook(blogManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
blogManager); blogManager);

View File

@@ -4,8 +4,6 @@ import com.rometools.rome.feed.synd.SyndFeed;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
@@ -32,17 +30,14 @@ import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
class FeedFactoryImpl implements FeedFactory { class FeedFactoryImpl implements FeedFactory {
private final CryptoComponent cryptoComponent;
private final AuthorFactory authorFactory; private final AuthorFactory authorFactory;
private final BlogFactory blogFactory; private final BlogFactory blogFactory;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final Clock clock; private final Clock clock;
@Inject @Inject
FeedFactoryImpl(CryptoComponent cryptoComponent, FeedFactoryImpl(AuthorFactory authorFactory, BlogFactory blogFactory,
AuthorFactory authorFactory, BlogFactory blogFactory,
ClientHelper clientHelper, Clock clock) { ClientHelper clientHelper, Clock clock) {
this.cryptoComponent = cryptoComponent;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
this.blogFactory = blogFactory; this.blogFactory = blogFactory;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
@@ -55,10 +50,7 @@ class FeedFactoryImpl implements FeedFactory {
if (title == null) title = "RSS"; if (title == null) title = "RSS";
else title = StringUtils.truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH); else title = StringUtils.truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH);
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair(); LocalAuthor localAuthor = authorFactory.createLocalAuthor(title);
LocalAuthor localAuthor = authorFactory.createLocalAuthor(title,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
Blog blog = blogFactory.createFeedBlog(localAuthor); Blog blog = blogFactory.createFeedBlog(localAuthor);
long added = clock.currentTimeMillis(); long added = clock.currentTimeMillis();
@@ -80,7 +72,7 @@ class FeedFactoryImpl implements FeedFactory {
BdfList authorList = d.getList(KEY_FEED_AUTHOR); BdfList authorList = d.getList(KEY_FEED_AUTHOR);
byte[] privateKey = d.getRaw(KEY_FEED_PRIVATE_KEY); byte[] privateKey = d.getRaw(KEY_FEED_PRIVATE_KEY);
Author author = clientHelper.parseAndValidateAuthor(authorList); Author author = clientHelper.parseAndValidateAuthor(authorList);
LocalAuthor localAuthor = authorFactory.createLocalAuthor( LocalAuthor localAuthor = new LocalAuthor(author.getId(),
author.getFormatVersion(), author.getName(), author.getFormatVersion(), author.getName(),
author.getPublicKey(), privateKey); author.getPublicKey(), privateKey);
Blog blog = blogFactory.createFeedBlog(localAuthor); Blog blog = blogFactory.createFeedBlog(localAuthor);

View File

@@ -20,11 +20,11 @@ import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent; import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -32,6 +32,7 @@ import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogManager.RemoveBlogHook;
import org.briarproject.briar.api.blog.BlogPost; import org.briarproject.briar.api.blog.BlogPost;
import org.briarproject.briar.api.blog.BlogPostFactory; import org.briarproject.briar.api.blog.BlogPostFactory;
import org.briarproject.briar.api.feed.Feed; import org.briarproject.briar.api.feed.Feed;
@@ -75,8 +76,8 @@ import static org.briarproject.briar.util.HtmlUtils.clean;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
class FeedManagerImpl implements FeedManager, Client, EventListener, class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook,
BlogManager.RemoveBlogHook { RemoveBlogHook {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(FeedManagerImpl.class.getName()); Logger.getLogger(FeedManagerImpl.class.getName());
@@ -136,7 +137,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
Group g = getLocalGroup(); Group g = getLocalGroup();
// Return if we've already set the local group up // Return if we've already set the local group up
if (db.containsGroup(txn, g.getId())) return; if (db.containsGroup(txn, g.getId())) return;

View File

@@ -24,8 +24,7 @@ public class FeedModule {
FeedManager provideFeedManager(FeedManagerImpl feedManager, FeedManager provideFeedManager(FeedManagerImpl feedManager,
LifecycleManager lifecycleManager, EventBus eventBus, LifecycleManager lifecycleManager, EventBus eventBus,
BlogManager blogManager) { BlogManager blogManager) {
lifecycleManager.registerOpenDatabaseHook(feedManager);
lifecycleManager.registerClient(feedManager);
eventBus.addListener(feedManager); eventBus.addListener(feedManager);
blogManager.registerRemoveBlogHook(feedManager); blogManager.registerRemoveBlogHook(feedManager);
return feedManager; return feedManager;

View File

@@ -19,8 +19,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo; import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -67,7 +67,7 @@ import static org.briarproject.briar.introduction.MessageType.REQUEST;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class IntroductionManagerImpl extends ConversationClientImpl class IntroductionManagerImpl extends ConversationClientImpl
implements IntroductionManager, Client, ContactHook, implements IntroductionManager, OpenDatabaseHook, ContactHook,
ClientVersioningHook { ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager; private final ClientVersioningManager clientVersioningManager;
@@ -115,7 +115,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to store protocol sessions // Create a local group to store protocol sessions
if (db.containsGroup(txn, localGroup.getId())) return; if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup); db.addGroup(txn, localGroup);

View File

@@ -51,7 +51,7 @@ public class IntroductionModule {
ConversationManager conversationManager, ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
IntroductionManagerImpl introductionManager) { IntroductionManagerImpl introductionManager) {
lifecycleManager.registerClient(introductionManager); lifecycleManager.registerOpenDatabaseHook(introductionManager);
contactManager.registerContactHook(introductionManager); contactManager.registerContactHook(introductionManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, validationManager.registerIncomingMessageHook(CLIENT_ID,
MAJOR_VERSION, introductionManager); MAJOR_VERSION, introductionManager);

View File

@@ -12,8 +12,8 @@ import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -50,7 +50,8 @@ import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class MessagingManagerImpl extends ConversationClientImpl class MessagingManagerImpl extends ConversationClientImpl
implements MessagingManager, Client, ContactHook, ClientVersioningHook { implements MessagingManager, OpenDatabaseHook, ContactHook,
ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager; private final ClientVersioningManager clientVersioningManager;
private final ContactGroupFactory contactGroupFactory; private final ContactGroupFactory contactGroupFactory;
@@ -66,7 +67,7 @@ class MessagingManagerImpl extends ConversationClientImpl
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up // Create a local group to indicate that we've set this client up
Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID, Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
MAJOR_VERSION); MAJOR_VERSION);

View File

@@ -58,7 +58,7 @@ public class MessagingModule {
ConversationManager conversationManager, ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
MessagingManagerImpl messagingManager) { MessagingManagerImpl messagingManager) {
lifecycleManager.registerClient(messagingManager); lifecycleManager.registerOpenDatabaseHook(messagingManager);
contactManager.registerContactHook(messagingManager); contactManager.registerContactHook(messagingManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
messagingManager); messagingManager);

View File

@@ -14,8 +14,8 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -62,7 +62,7 @@ import static org.briarproject.briar.privategroup.invitation.Role.PEER;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class GroupInvitationManagerImpl extends ConversationClientImpl class GroupInvitationManagerImpl extends ConversationClientImpl
implements GroupInvitationManager, Client, ContactHook, implements GroupInvitationManager, OpenDatabaseHook, ContactHook,
PrivateGroupHook, ClientVersioningHook { PrivateGroupHook, ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager; private final ClientVersioningManager clientVersioningManager;
@@ -101,7 +101,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
} }
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up // Create a local group to indicate that we've set this client up
Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID, Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
MAJOR_VERSION); MAJOR_VERSION);

View File

@@ -42,7 +42,7 @@ public class GroupInvitationModule {
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
ConversationManager conversationManager, ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager) { ClientVersioningManager clientVersioningManager) {
lifecycleManager.registerClient(groupInvitationManager); lifecycleManager.registerOpenDatabaseHook(groupInvitationManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
groupInvitationManager); groupInvitationManager);
contactManager.registerContactHook(groupInvitationManager); contactManager.registerContactHook(groupInvitationManager);

View File

@@ -13,8 +13,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -55,7 +55,7 @@ import static org.briarproject.briar.sharing.State.SHARING;
@NotNullByDefault @NotNullByDefault
abstract class SharingManagerImpl<S extends Shareable> abstract class SharingManagerImpl<S extends Shareable>
extends ConversationClientImpl extends ConversationClientImpl
implements SharingManager<S>, Client, ContactHook, implements SharingManager<S>, OpenDatabaseHook, ContactHook,
ClientVersioningHook { ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager; private final ClientVersioningManager clientVersioningManager;
@@ -92,7 +92,7 @@ abstract class SharingManagerImpl<S extends Shareable>
protected abstract int getShareableMajorVersion(); protected abstract int getShareableMajorVersion();
@Override @Override
public void createLocalState(Transaction txn) throws DbException { public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up // Create a local group to indicate that we've set this client up
Group localGroup = contactGroupFactory.createLocalGroup(getClientId(), Group localGroup = contactGroupFactory.createLocalGroup(getClientId(),
getMajorVersion()); getMajorVersion());

View File

@@ -76,7 +76,7 @@ public class SharingModule {
ConversationManager conversationManager, BlogManager blogManager, ConversationManager conversationManager, BlogManager blogManager,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
BlogSharingManagerImpl blogSharingManager) { BlogSharingManagerImpl blogSharingManager) {
lifecycleManager.registerClient(blogSharingManager); lifecycleManager.registerOpenDatabaseHook(blogSharingManager);
contactManager.registerContactHook(blogSharingManager); contactManager.registerContactHook(blogSharingManager);
validationManager.registerIncomingMessageHook( validationManager.registerIncomingMessageHook(
BlogSharingManager.CLIENT_ID, BlogSharingManager.MAJOR_VERSION, BlogSharingManager.CLIENT_ID, BlogSharingManager.MAJOR_VERSION,
@@ -135,7 +135,7 @@ public class SharingModule {
ConversationManager conversationManager, ForumManager forumManager, ConversationManager conversationManager, ForumManager forumManager,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
ForumSharingManagerImpl forumSharingManager) { ForumSharingManagerImpl forumSharingManager) {
lifecycleManager.registerClient(forumSharingManager); lifecycleManager.registerOpenDatabaseHook(forumSharingManager);
contactManager.registerContactHook(forumSharingManager); contactManager.registerContactHook(forumSharingManager);
validationManager.registerIncomingMessageHook( validationManager.registerIncomingMessageHook(
ForumSharingManager.CLIENT_ID, ForumSharingManager.CLIENT_ID,

View File

@@ -5,8 +5,6 @@ import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
@@ -74,7 +72,6 @@ public class TestDataCreatorImpl implements TestDataCreator {
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final MessageTracker messageTracker; private final MessageTracker messageTracker;
private final BlogPostFactory blogPostFactory; private final BlogPostFactory blogPostFactory;
private final CryptoComponent cryptoComponent;
private final DatabaseComponent db; private final DatabaseComponent db;
private final IdentityManager identityManager; private final IdentityManager identityManager;
@@ -94,9 +91,8 @@ public class TestDataCreatorImpl implements TestDataCreator {
TestDataCreatorImpl(AuthorFactory authorFactory, Clock clock, TestDataCreatorImpl(AuthorFactory authorFactory, Clock clock,
PrivateMessageFactory privateMessageFactory, PrivateMessageFactory privateMessageFactory,
ClientHelper clientHelper, MessageTracker messageTracker, ClientHelper clientHelper, MessageTracker messageTracker,
BlogPostFactory blogPostFactory, CryptoComponent cryptoComponent, BlogPostFactory blogPostFactory, DatabaseComponent db,
DatabaseComponent db, IdentityManager identityManager, IdentityManager identityManager, ContactManager contactManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager, TransportPropertyManager transportPropertyManager,
MessagingManager messagingManager, BlogManager blogManager, MessagingManager messagingManager, BlogManager blogManager,
ForumManager forumManager, @IoExecutor Executor ioExecutor) { ForumManager forumManager, @IoExecutor Executor ioExecutor) {
@@ -106,7 +102,6 @@ public class TestDataCreatorImpl implements TestDataCreator {
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.messageTracker = messageTracker; this.messageTracker = messageTracker;
this.blogPostFactory = blogPostFactory; this.blogPostFactory = blogPostFactory;
this.cryptoComponent = cryptoComponent;
this.db = db; this.db = db;
this.identityManager = identityManager; this.identityManager = identityManager;
this.contactManager = contactManager; this.contactManager = contactManager;
@@ -150,14 +145,14 @@ public class TestDataCreatorImpl implements TestDataCreator {
List<Contact> contacts = new ArrayList<>(numContacts); List<Contact> contacts = new ArrayList<>(numContacts);
LocalAuthor localAuthor = identityManager.getLocalAuthor(); LocalAuthor localAuthor = identityManager.getLocalAuthor();
for (int i = 0; i < numContacts; i++) { for (int i = 0; i < numContacts; i++) {
LocalAuthor author = getRandomAuthor(); LocalAuthor remote = getRandomAuthor();
Contact contact = addContact(localAuthor.getId(), author); Contact contact = addContact(localAuthor.getId(), remote);
contacts.add(contact); contacts.add(contact);
} }
return contacts; return contacts;
} }
private Contact addContact(AuthorId localAuthorId, LocalAuthor author) private Contact addContact(AuthorId localAuthorId, LocalAuthor remote)
throws DbException { throws DbException {
// prepare to add contact // prepare to add contact
@@ -173,7 +168,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
ContactId contactId = contactManager ContactId contactId = contactManager
.addContact(txn, author, localAuthorId, secretKey, .addContact(txn, remote, localAuthorId, secretKey,
timestamp, true, verified, true); timestamp, true, verified, true);
if (random.nextBoolean()) { if (random.nextBoolean()) {
contactManager contactManager
@@ -187,24 +182,18 @@ public class TestDataCreatorImpl implements TestDataCreator {
} }
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("Added contact " + author.getName()); LOG.info("Added contact " + remote.getName());
LOG.info("with transport properties: " + props.toString()); LOG.info("with transport properties: " + props.toString());
} }
localAuthors.put(contact, author); localAuthors.put(contact, remote);
return contact; return contact;
} }
@Override @Override
public Contact addContact(String name) throws DbException { public Contact addContact(String name) throws DbException {
LocalAuthor localAuthor = identityManager.getLocalAuthor(); LocalAuthor localAuthor = identityManager.getLocalAuthor();
return addContact(localAuthor.getId(), getAuthor(name)); LocalAuthor remote = authorFactory.createLocalAuthor(name);
} return addContact(localAuthor.getId(), remote);
private LocalAuthor getAuthor(String name) {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
return authorFactory.createLocalAuthor(name, publicKey, privateKey);
} }
private String getRandomAuthorName() { private String getRandomAuthorName() {
@@ -213,7 +202,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
} }
private LocalAuthor getRandomAuthor() { private LocalAuthor getRandomAuthor() {
return getAuthor(getRandomAuthorName()); return authorFactory.createLocalAuthor(getRandomAuthorName());
} }
private SecretKey getSecretKey() { private SecretKey getSecretKey() {

View File

@@ -112,7 +112,7 @@ public class BlogManagerImplTest extends BriarTestCase {
} }
@Test @Test
public void testCreateLocalState() throws DbException { public void testOpenDatabaseHook() throws DbException {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -123,7 +123,7 @@ public class BlogManagerImplTest extends BriarTestCase {
oneOf(db).addGroup(txn, blog1.getGroup()); oneOf(db).addGroup(txn, blog1.getGroup());
}}); }});
blogManager.createLocalState(txn); blogManager.onDatabaseOpened(txn);
context.assertIsSatisfied(); context.assertIsSatisfied();
} }

View File

@@ -21,9 +21,7 @@ import java.util.Iterator;
import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotNull;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE; import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.MessageType.COMMENT; import static org.briarproject.briar.api.blog.MessageType.COMMENT;
import static org.briarproject.briar.api.blog.MessageType.POST; import static org.briarproject.briar.api.blog.MessageType.POST;
@@ -50,10 +48,8 @@ public class BlogManagerIntegrationTest
author0 = identityManager0.getLocalAuthor(); author0 = identityManager0.getLocalAuthor();
author1 = identityManager1.getLocalAuthor(); author1 = identityManager1.getLocalAuthor();
rssAuthor = c0.getAuthorFactory().createLocalAuthor( String rssTitle = getRandomString(MAX_AUTHOR_NAME_LENGTH);
getRandomString(MAX_AUTHOR_NAME_LENGTH), rssAuthor = c0.getAuthorFactory().createLocalAuthor(rssTitle);
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
getRandomBytes(123));
blogManager0 = c0.getBlogManager(); blogManager0 = c0.getBlogManager();
blogManager1 = c1.getBlogManager(); blogManager1 = c1.getBlogManager();

View File

@@ -1,7 +1,7 @@
package org.briarproject.briar.feed; package org.briarproject.briar.feed;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.contact.ContactModule;
import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoExecutorModule;
@@ -51,8 +51,8 @@ public class FeedManagerIntegrationTest extends BriarTestCase {
injectEagerSingletons(component); injectEagerSingletons(component);
IdentityManager identityManager = component.getIdentityManager(); IdentityManager identityManager = component.getIdentityManager();
LocalAuthor localAuthor = identityManager.createLocalAuthor("feedTest"); Identity identity = identityManager.createIdentity("feedTest");
identityManager.registerLocalAuthor(localAuthor); identityManager.registerIdentity(identity);
lifecycleManager = component.getLifecycleManager(); lifecycleManager = component.getLifecycleManager();
lifecycleManager.startServices(getSecretKey()); lifecycleManager.startServices(getSecretKey());

View File

@@ -58,10 +58,8 @@ public class IntroductionCryptoIntegrationTest extends BrambleTestCase {
crypto = new IntroductionCryptoImpl(cryptoComponent, clientHelper); crypto = new IntroductionCryptoImpl(cryptoComponent, clientHelper);
introducer = getRealAuthor(authorFactory); introducer = getRealAuthor(authorFactory);
LocalAuthor introducee1 = LocalAuthor introducee1 = getRealLocalAuthor(authorFactory);
getRealLocalAuthor(cryptoComponent, authorFactory); LocalAuthor introducee2 = getRealLocalAuthor(authorFactory);
LocalAuthor introducee2 =
getRealLocalAuthor(cryptoComponent, authorFactory);
boolean isAlice = boolean isAlice =
crypto.isAlice(introducee1.getId(), introducee2.getId()); crypto.isAlice(introducee1.getId(), introducee2.getId());
alice = isAlice ? introducee1 : introducee2; alice = isAlice ? introducee1 : introducee2;

View File

@@ -2,7 +2,6 @@ package org.briarproject.briar.messaging;
import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -70,12 +69,8 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
@Test @Test
public void testForumPostFitsIntoRecord() throws Exception { public void testForumPostFitsIntoRecord() throws Exception {
// Create a maximum-length author // Create a maximum-length author
int formatVersion = Integer.MAX_VALUE;
String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH); String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH]; LocalAuthor author = authorFactory.createLocalAuthor(authorName);
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
LocalAuthor author = authorFactory.createLocalAuthor(formatVersion,
authorName, authorPublic, privateKey.getEncoded());
// Create a maximum-length forum post // Create a maximum-length forum post
GroupId groupId = new GroupId(getRandomId()); GroupId groupId = new GroupId(getRandomId());
long timestamp = Long.MAX_VALUE; long timestamp = Long.MAX_VALUE;

View File

@@ -6,8 +6,8 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -75,13 +75,14 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
@Test @Test
public void testWriteAndRead() throws Exception { public void testWriteAndRead() throws Exception {
// Create the identities // Create the identities
LocalAuthor aliceAuthor = Identity aliceIdentity =
alice.getIdentityManager().createLocalAuthor("Alice"); alice.getIdentityManager().createIdentity("Alice");
LocalAuthor bobAuthor = Identity bobIdentity = bob.getIdentityManager().createIdentity("Bob");
bob.getIdentityManager().createLocalAuthor("Bob");
// Set up the devices and get the contact IDs // Set up the devices and get the contact IDs
ContactId bobId = setUp(alice, aliceAuthor, bobAuthor, true); ContactId bobId = setUp(alice, aliceIdentity,
ContactId aliceId = setUp(bob, bobAuthor, aliceAuthor, false); bobIdentity.getLocalAuthor(), true);
ContactId aliceId = setUp(bob, bobIdentity,
aliceIdentity.getLocalAuthor(), false);
// Add a private message listener // Add a private message listener
PrivateMessageListener listener = new PrivateMessageListener(); PrivateMessageListener listener = new PrivateMessageListener();
bob.getEventBus().addListener(listener); bob.getEventBus().addListener(listener);
@@ -100,10 +101,10 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
} }
private ContactId setUp(SimplexMessagingIntegrationTestComponent device, private ContactId setUp(SimplexMessagingIntegrationTestComponent device,
LocalAuthor local, Author remote, boolean alice) throws Exception { Identity local, Author remote, boolean alice) throws Exception {
// Add an identity for the user // Add an identity for the user
IdentityManager identityManager = device.getIdentityManager(); IdentityManager identityManager = device.getIdentityManager();
identityManager.registerLocalAuthor(local); identityManager.registerIdentity(local);
// Start the lifecycle manager // Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager(); LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices(getSecretKey()); lifecycleManager.startServices(getSecretKey());

View File

@@ -149,7 +149,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
} }
@Test @Test
public void testCreateLocalStateFirstTime() throws Exception { public void testDatabaseOpenHookFirstTime() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID, oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
MAJOR_VERSION); MAJOR_VERSION);
@@ -161,11 +161,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
will(returnValue(Collections.singletonList(contact))); will(returnValue(Collections.singletonList(contact)));
}}); }});
expectAddingContact(contact); expectAddingContact(contact);
groupInvitationManager.createLocalState(txn); groupInvitationManager.onDatabaseOpened(txn);
} }
@Test @Test
public void testCreateLocalStateSubsequentTime() throws Exception { public void testOpenDatabaseHookSubsequentTime() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID, oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
MAJOR_VERSION); MAJOR_VERSION);
@@ -173,7 +173,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
oneOf(db).containsGroup(txn, localGroup.getId()); oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(true)); will(returnValue(true));
}}); }});
groupInvitationManager.createLocalState(txn); groupInvitationManager.onDatabaseOpened(txn);
} }
private void expectAddingContact(Contact c) throws Exception { private void expectAddingContact(Contact c) throws Exception {

View File

@@ -94,7 +94,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
} }
@Test @Test
public void testCreateLocalStateFirstTimeWithExistingContact() public void testOpenDatabaseHookFirstTimeWithExistingContact()
throws Exception { throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
@@ -113,7 +113,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
// Set things up for the contact // Set things up for the contact
expectAddingContact(txn); expectAddingContact(txn);
blogSharingManager.createLocalState(txn); blogSharingManager.onDatabaseOpened(txn);
} }
private void expectAddingContact(Transaction txn) throws Exception { private void expectAddingContact(Transaction txn) throws Exception {
@@ -149,7 +149,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
} }
@Test @Test
public void testCreateLocalStateSubsequentTime() throws Exception { public void testOpenDatabaseHookSubsequentTime() throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -161,7 +161,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
will(returnValue(true)); will(returnValue(true));
}}); }});
blogSharingManager.createLocalState(txn); blogSharingManager.onDatabaseOpened(txn);
} }
@Test @Test

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -274,12 +275,15 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
} }
private void createAndRegisterIdentities() { private void createAndRegisterIdentities() {
author0 = identityManager0.createLocalAuthor(AUTHOR0); Identity identity0 = identityManager0.createIdentity(AUTHOR0);
identityManager0.registerLocalAuthor(author0); identityManager0.registerIdentity(identity0);
author1 = identityManager1.createLocalAuthor(AUTHOR1); author0 = identity0.getLocalAuthor();
identityManager1.registerLocalAuthor(author1); Identity identity1 = identityManager0.createIdentity(AUTHOR1);
author2 = identityManager2.createLocalAuthor(AUTHOR2); identityManager1.registerIdentity(identity1);
identityManager2.registerLocalAuthor(author2); author1 = identity1.getLocalAuthor();
Identity identity2 = identityManager0.createIdentity(AUTHOR2);
identityManager2.registerIdentity(identity2);
author2 = identity2.getLocalAuthor();
} }
protected void addDefaultContacts() throws Exception { protected void addDefaultContacts() throws Exception {

View File

@@ -1,7 +1,5 @@
package org.briarproject.briar.test; package org.briarproject.briar.test;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
@@ -10,8 +8,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.MessageTracker.GroupCount; import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -27,23 +24,20 @@ public class BriarTestUtils {
} }
public static void assertGroupCount(MessageTracker tracker, GroupId g, public static void assertGroupCount(MessageTracker tracker, GroupId g,
long msgCount, long unreadCount) throws DbException { long msgCount, long unreadCount) throws DbException {
GroupCount c1 = tracker.getGroupCount(g); GroupCount c1 = tracker.getGroupCount(g);
assertEquals(msgCount, c1.getMsgCount()); assertEquals(msgCount, c1.getMsgCount());
assertEquals(unreadCount, c1.getUnreadCount()); assertEquals(unreadCount, c1.getUnreadCount());
} }
public static Author getRealAuthor(AuthorFactory authorFactory) { public static Author getRealAuthor(AuthorFactory authorFactory) {
return authorFactory.createAuthor(getRandomString(5), String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
getRandomBytes(MAX_PUBLIC_KEY_LENGTH)); return authorFactory.createLocalAuthor(name);
} }
public static LocalAuthor getRealLocalAuthor( public static LocalAuthor getRealLocalAuthor(AuthorFactory authorFactory) {
CryptoComponent cryptoComponent, AuthorFactory authorFactory) { String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair(); return authorFactory.createLocalAuthor(name);
return authorFactory.createLocalAuthor(getRandomString(5),
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
} }
} }