Move local author creation into IdentityManager.

This commit is contained in:
akwizgran
2018-07-20 13:55:30 +01:00
parent 81cbb7e843
commit 8283760e8a
20 changed files with 177 additions and 143 deletions

View File

@@ -16,7 +16,7 @@ public interface ContactManager {
/** /**
* Registers a hook to be called whenever a contact is added or removed. * Registers a hook to be called whenever a contact is added or removed.
* This method should be called before * This method should be called before
* {@link LifecycleManager#startServices(String)}. * {@link LifecycleManager#startServices()}.
*/ */
void registerContactHook(ContactHook hook); void registerContactHook(ContactHook hook);

View File

@@ -21,10 +21,5 @@ public interface DatabaseConfig {
@Nullable @Nullable
SecretKey getEncryptionKey(); SecretKey getEncryptionKey();
void setLocalAuthorName(String nickname);
@Nullable
String getLocalAuthorName();
long getMaxSize(); long getMaxSize();
} }

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.api.identity; package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
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.Author.Status; import org.briarproject.bramble.api.identity.Author.Status;
@@ -9,29 +10,40 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
public interface IdentityManager { public interface IdentityManager {
/** /**
* Stores the local pseudonym. * Creates a local identity with the given name.
*/ */
void registerLocalAuthor(LocalAuthor a) throws DbException; @CryptoExecutor
LocalAuthor createLocalAuthor(String name);
/** /**
* Returns the cached main local identity, non-blocking, or loads it from * Registers the given local identity with the manager. The identity is
* the db, blocking * not stored until {@link #storeLocalAuthor()} is called.
*/
void registerLocalAuthor(LocalAuthor a);
/**
* 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.
*/ */
LocalAuthor getLocalAuthor() throws DbException; LocalAuthor getLocalAuthor() throws DbException;
/** /**
* Returns the cached main local identity, non-blocking, or loads it from * Returns the cached local identity or loads it from the database.
* the db, blocking, within the given Transaction.
*/ */
LocalAuthor getLocalAuthor(Transaction txn) throws DbException; LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/** /**
* Returns the trust-level status of the author * Returns the {@link Status} of the given author.
*/ */
Status getAuthorStatus(AuthorId a) throws DbException; Status getAuthorStatus(AuthorId a) throws DbException;
/** /**
* Returns the trust-level status of the author * Returns the {@link Status} of the given author.
*/ */
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException; Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;

View File

@@ -6,8 +6,6 @@ import org.briarproject.bramble.api.sync.Client;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
/** /**
* Manages the lifecycle of the app, starting {@link Client Clients}, starting * Manages the lifecycle of the app, starting {@link Client Clients}, starting
* and stopping {@link Service Services}, shutting down * and stopping {@link Service Services}, shutting down
@@ -18,7 +16,7 @@ import javax.annotation.Nullable;
public interface LifecycleManager { public interface LifecycleManager {
/** /**
* The result of calling {@link #startServices(String)}. * The result of calling {@link #startServices()}.
*/ */
enum StartResult { enum StartResult {
ALREADY_RUNNING, ALREADY_RUNNING,
@@ -44,28 +42,27 @@ public interface LifecycleManager {
/** /**
* 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(String)}. * should be called before {@link #startServices()}.
*/ */
void registerService(Service s); void registerService(Service s);
/** /**
* Registers a {@link Client} to be started. This method should be called * Registers a {@link Client} to be started. This method should be called
* before {@link #startServices(String)}. * before {@link #startServices()}.
*/ */
void registerClient(Client c); 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(String)}. * should be called before {@link #startServices()}.
*/ */
void registerForShutdown(ExecutorService e); void registerForShutdown(ExecutorService e);
/** /**
* Opens the {@link DatabaseComponent}, optionally creates a local author * Opens the {@link DatabaseComponent} and starts any registered
* with the provided nickname, and starts any registered
* {@link Client Clients} and {@link Service Services}. * {@link Client Clients} and {@link Service Services}.
*/ */
StartResult startServices(@Nullable String nickname); StartResult startServices();
/** /**
* Stops any registered {@link Service Services}, shuts down any * Stops any registered {@link Service Services}, shuts down any

View File

@@ -35,7 +35,7 @@ public interface ValidationManager {
/** /**
* Registers the message validator for the given client. This method * Registers the message validator for the given client. This method
* should be called before {@link LifecycleManager#startServices(String)}. * should be called before {@link LifecycleManager#startServices()}.
*/ */
void registerMessageValidator(ClientId c, int majorVersion, void registerMessageValidator(ClientId c, int majorVersion,
MessageValidator v); MessageValidator v);
@@ -43,8 +43,7 @@ public interface ValidationManager {
/** /**
* Registers the incoming message hook for the given client. The hook will * Registers the incoming message hook for the given client. The hook will
* be called once for each incoming message that passes validation. This * be called once for each incoming message that passes validation. This
* method should be called before * method should be called before {@link LifecycleManager#startServices()}.
* {@link LifecycleManager#startServices(String)}.
*/ */
void registerIncomingMessageHook(ClientId c, int majorVersion, void registerIncomingMessageHook(ClientId c, int majorVersion,
IncomingMessageHook hook); IncomingMessageHook hook);

View File

@@ -25,7 +25,7 @@ public interface ClientVersioningManager {
/** /**
* Registers a client that will be advertised to contacts. The hook will * Registers a client that will be advertised to contacts. The hook will
* be called when the visibility of the client changes. This method should * be called when the visibility of the client changes. This method should
* be called before {@link LifecycleManager#startServices(String)}. * be called before {@link LifecycleManager#startServices()}.
*/ */
void registerClient(ClientId clientId, int majorVersion, int minorVersion, void registerClient(ClientId clientId, int majorVersion, int minorVersion,
ClientVersioningHook hook); ClientVersioningHook hook);

View File

@@ -1,10 +1,13 @@
package org.briarproject.bramble.identity; package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
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.identity.Author.Status; import org.briarproject.bramble.api.identity.Author.Status;
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.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -21,6 +24,8 @@ import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN; import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED; import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED; import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -30,25 +35,51 @@ class IdentityManagerImpl implements IdentityManager {
Logger.getLogger(IdentityManagerImpl.class.getName()); Logger.getLogger(IdentityManagerImpl.class.getName());
private final DatabaseComponent db; private final DatabaseComponent db;
private final CryptoComponent crypto;
private final AuthorFactory authorFactory;
// The local author is immutable so we can cache it // The local author is immutable so we can cache it
@Nullable @Nullable
private volatile LocalAuthor cachedAuthor; private volatile LocalAuthor cachedAuthor;
@Inject @Inject
IdentityManagerImpl(DatabaseComponent db) { IdentityManagerImpl(DatabaseComponent db, CryptoComponent crypto,
AuthorFactory authorFactory) {
this.db = db; this.db = db;
this.crypto = crypto;
this.authorFactory = authorFactory;
} }
@Override @Override
public void registerLocalAuthor(LocalAuthor localAuthor) public LocalAuthor createLocalAuthor(String name) {
throws DbException { long start = now();
KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
LocalAuthor localAuthor = authorFactory.createLocalAuthor(name,
publicKey, privateKey);
logDuration(LOG, "Creating local author", start);
return localAuthor;
}
@Override
public void registerLocalAuthor(LocalAuthor a) {
cachedAuthor = a;
LOG.info("Local author registered");
}
@Override
public void storeLocalAuthor() throws DbException {
LocalAuthor cached = cachedAuthor;
if (cached == null) {
LOG.info("No local author to store");
return;
}
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, cached);
db.commitTransaction(txn); db.commitTransaction(txn);
cachedAuthor = localAuthor; LOG.info("Local author stored");
LOG.info("Local author registered");
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
} }

View File

@@ -1,7 +1,5 @@
package org.briarproject.bramble.lifecycle; package org.briarproject.bramble.lifecycle;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooNewException;
import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DataTooOldException;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
@@ -9,9 +7,7 @@ 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.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
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.identity.LocalAuthor;
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;
@@ -26,7 +22,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
@@ -60,8 +55,6 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private final List<Service> services; private final List<Service> services;
private final List<Client> clients; private final List<Client> clients;
private final List<ExecutorService> executors; private final List<ExecutorService> executors;
private final CryptoComponent crypto;
private final AuthorFactory authorFactory;
private final IdentityManager identityManager; 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);
@@ -72,12 +65,9 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
@Inject @Inject
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus, LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
CryptoComponent crypto, AuthorFactory authorFactory,
IdentityManager identityManager) { IdentityManager identityManager) {
this.db = db; this.db = db;
this.eventBus = eventBus; this.eventBus = eventBus;
this.crypto = crypto;
this.authorFactory = authorFactory;
this.identityManager = identityManager; this.identityManager = identityManager;
services = new CopyOnWriteArrayList<>(); services = new CopyOnWriteArrayList<>();
clients = new CopyOnWriteArrayList<>(); clients = new CopyOnWriteArrayList<>();
@@ -104,25 +94,8 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
executors.add(e); executors.add(e);
} }
private LocalAuthor createLocalAuthor(String nickname) {
long start = now();
KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
LocalAuthor localAuthor = authorFactory
.createLocalAuthor(nickname, publicKey, privateKey);
logDuration(LOG, "Creating local author", start);
return localAuthor;
}
private void registerLocalAuthor(LocalAuthor author) throws DbException {
long start = now();
identityManager.registerLocalAuthor(author);
logDuration(LOG, "Registering local author", start);
}
@Override @Override
public StartResult startServices(@Nullable String nickname) { public StartResult startServices() {
if (!startStopSemaphore.tryAcquire()) { if (!startStopSemaphore.tryAcquire()) {
LOG.info("Already starting or stopping"); LOG.info("Already starting or stopping");
return ALREADY_RUNNING; return ALREADY_RUNNING;
@@ -134,10 +107,7 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
boolean reopened = db.open(this); boolean reopened = db.open(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();
if (nickname != null) {
registerLocalAuthor(createLocalAuthor(nickname));
}
state = STARTING_SERVICES; state = STARTING_SERVICES;
dbLatch.countDown(); dbLatch.countDown();

View File

@@ -1,10 +1,5 @@
package org.briarproject.bramble.lifecycle; package org.briarproject.bramble.lifecycle;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.lifecycle.ShutdownManager;
@@ -54,11 +49,9 @@ public class LifecycleModule {
@Provides @Provides
@Singleton @Singleton
LifecycleManager provideLifecycleManager(DatabaseComponent db, LifecycleManager provideLifecycleManager(
EventBus eventBus, CryptoComponent crypto, LifecycleManagerImpl lifecycleManager) {
AuthorFactory authorFactory, IdentityManager identityManager) { return lifecycleManager;
return new LifecycleManagerImpl(db, eventBus, crypto, authorFactory,
identityManager);
} }
@Provides @Provides

View File

@@ -2,15 +2,21 @@ package org.briarproject.bramble.identity;
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.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
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.identity.Author; import org.briarproject.bramble.api.identity.Author;
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.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;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
@@ -27,24 +33,48 @@ import static org.junit.Assert.assertEquals;
public class IdentityManagerImplTest extends BrambleMockTestCase { public class IdentityManagerImplTest extends BrambleMockTestCase {
private final IdentityManager identityManager;
private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final AuthorFactory authorFactory =
context.mock(AuthorFactory.class);
private final PublicKey publicKey = context.mock(PublicKey.class);
private final PrivateKey privateKey = 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 LocalAuthor localAuthor = getLocalAuthor();
private final Collection<LocalAuthor> localAuthors = private final Collection<LocalAuthor> localAuthors =
Collections.singletonList(localAuthor); Collections.singletonList(localAuthor);
private final String authorName = localAuthor.getName();
private final KeyPair keyPair = new KeyPair(publicKey, privateKey);
private final byte[] publicKeyBytes = localAuthor.getPublicKey();
private final byte[] privateKeyBytes = localAuthor.getPrivateKey();
private IdentityManager identityManager;
public IdentityManagerImplTest() { @Before
identityManager = new IdentityManagerImpl(db); public void setUp() {
identityManager = new IdentityManagerImpl(db, crypto, authorFactory);
} }
@Test @Test
public void testRegisterLocalAuthor() throws DbException { public void testCreateLocalAuthor() {
expectRegisterLocalAuthor(); context.checking(new Expectations() {{
identityManager.registerLocalAuthor(localAuthor); oneOf(crypto).generateSignatureKeyPair();
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.createLocalAuthor(authorName));
} }
private void expectRegisterLocalAuthor() throws DbException { @Test
public void testRegisterAndStoreLocalAuthor() throws DbException {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
will(returnValue(txn)); will(returnValue(txn));
@@ -52,6 +82,10 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
identityManager.registerLocalAuthor(localAuthor);
assertEquals(localAuthor, identityManager.getLocalAuthor());
identityManager.storeLocalAuthor();
} }
@Test @Test
@@ -69,7 +103,6 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetCachedLocalAuthor() throws DbException { public void testGetCachedLocalAuthor() throws DbException {
expectRegisterLocalAuthor();
identityManager.registerLocalAuthor(localAuthor); identityManager.registerLocalAuthor(localAuthor);
assertEquals(localAuthor, identityManager.getLocalAuthor()); assertEquals(localAuthor, identityManager.getLocalAuthor());
} }

View File

@@ -46,16 +46,6 @@ public class TestDatabaseConfig implements DatabaseConfig {
return key; return key;
} }
@Override
public void setLocalAuthorName(String nickname) {
}
@Override
public String getLocalAuthorName() {
return null;
}
@Override @Override
public long getMaxSize() { public long getMaxSize() {
return maxSize; return maxSize;

View File

@@ -11,7 +11,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import javax.annotation.Nullable;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
@@ -40,7 +39,7 @@ public class TestLifecycleModule {
} }
@Override @Override
public StartResult startServices(@Nullable String nickname) { public StartResult startServices() {
return StartResult.SUCCESS; return StartResult.SUCCESS;
} }
@@ -49,15 +48,15 @@ public class TestLifecycleModule {
} }
@Override @Override
public void waitForDatabase() throws InterruptedException { public void waitForDatabase() {
} }
@Override @Override
public void waitForStartup() throws InterruptedException { public void waitForStartup() {
} }
@Override @Override
public void waitForShutdown() throws InterruptedException { public void waitForShutdown() {
} }
@Override @Override

View File

@@ -21,8 +21,6 @@ class AndroidDatabaseConfig implements DatabaseConfig {
@Nullable @Nullable
private volatile SecretKey key = null; private volatile SecretKey key = null;
@Nullable
private volatile String nickname = null;
AndroidDatabaseConfig(File dbDir, File keyDir) { AndroidDatabaseConfig(File dbDir, File keyDir) {
this.dbDir = dbDir; this.dbDir = dbDir;
@@ -70,21 +68,6 @@ class AndroidDatabaseConfig implements DatabaseConfig {
this.key = key; this.key = key;
} }
@Override
public void setLocalAuthorName(String nickname) {
LOG.info("Setting local author name");
this.nickname = nickname;
}
@Override
@Nullable
public String getLocalAuthorName() {
String nickname = this.nickname;
if (LOG.isLoggable(INFO))
LOG.info("Local author name has been set: " + (nickname != null));
return nickname;
}
@Override @Override
@Nullable @Nullable
public SecretKey getEncryptionKey() { public SecretKey getEncryptionKey() {

View File

@@ -141,8 +141,7 @@ public class BriarService extends Service {
nm.cancel(REMINDER_NOTIFICATION_ID); nm.cancel(REMINDER_NOTIFICATION_ID);
// Start the services in a background thread // Start the services in a background thread
new Thread(() -> { new Thread(() -> {
String nickname = databaseConfig.getLocalAuthorName(); StartResult result = lifecycleManager.startServices();
StartResult result = lifecycleManager.startServices(nickname);
if (result == SUCCESS) { if (result == SUCCESS) {
started = true; started = true;
} else if (result == ALREADY_RUNNING) { } else if (result == ALREADY_RUNNING) {

View File

@@ -8,6 +8,8 @@ import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
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.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.controller.handler.ResultHandler; import org.briarproject.briar.android.controller.handler.ResultHandler;
import org.briarproject.briar.android.controller.handler.UiResultHandler; import org.briarproject.briar.android.controller.handler.UiResultHandler;
@@ -24,6 +26,8 @@ public class SetupControllerImpl extends PasswordControllerImpl
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SetupControllerImpl.class.getName()); Logger.getLogger(SetupControllerImpl.class.getName());
private final IdentityManager identityManager;
@Nullable @Nullable
private volatile SetupActivity setupActivity; private volatile SetupActivity setupActivity;
@@ -31,9 +35,11 @@ public class SetupControllerImpl extends PasswordControllerImpl
SetupControllerImpl(SharedPreferences briarPrefs, SetupControllerImpl(SharedPreferences briarPrefs,
DatabaseConfig databaseConfig, DatabaseConfig databaseConfig,
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto, @CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
PasswordStrengthEstimator strengthEstimator) { PasswordStrengthEstimator strengthEstimator,
IdentityManager identityManager) {
super(briarPrefs, databaseConfig, cryptoExecutor, crypto, super(briarPrefs, databaseConfig, cryptoExecutor, crypto,
strengthEstimator); strengthEstimator);
this.identityManager = identityManager;
} }
@Override @Override
@@ -102,13 +108,14 @@ public class SetupControllerImpl extends PasswordControllerImpl
if (password == null) throw new IllegalStateException(); if (password == null) throw new IllegalStateException();
cryptoExecutor.execute(() -> { cryptoExecutor.execute(() -> {
LOG.info("Creating account"); LOG.info("Creating account");
databaseConfig.setLocalAuthorName(authorName); LocalAuthor localAuthor =
identityManager.createLocalAuthor(authorName);
identityManager.registerLocalAuthor(localAuthor);
SecretKey key = crypto.generateSecretKey(); SecretKey key = crypto.generateSecretKey();
databaseConfig.setEncryptionKey(key);
String hex = encryptDatabaseKey(key, password); String hex = encryptDatabaseKey(key, password);
storeEncryptedDatabaseKey(hex); storeEncryptedDatabaseKey(hex);
databaseConfig.setEncryptionKey(key);
resultHandler.onResult(null); resultHandler.onResult(null);
}); });
} }
} }

View File

@@ -7,6 +7,8 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
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.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.ImmediateExecutor; import org.briarproject.bramble.test.ImmediateExecutor;
import org.jmock.Expectations; import org.jmock.Expectations;
@@ -23,6 +25,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
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.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.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;
@@ -39,12 +42,15 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final PasswordStrengthEstimator estimator = private final PasswordStrengthEstimator estimator =
context.mock(PasswordStrengthEstimator.class); context.mock(PasswordStrengthEstimator.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final SetupActivity setupActivity; private final SetupActivity setupActivity;
private final Executor cryptoExecutor = new ImmediateExecutor(); private final Executor cryptoExecutor = new ImmediateExecutor();
private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH); private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
private final String password = "some.strong.pass"; private final String password = "some.strong.pass";
private final LocalAuthor localAuthor = getLocalAuthor();
private final byte[] encryptedKey = getRandomBytes(123); private final byte[] encryptedKey = getRandomBytes(123);
private final SecretKey key = getSecretKey(); private final SecretKey key = getSecretKey();
private final File testDir = getTestDirectory(); private final File testDir = getTestDirectory();
@@ -74,25 +80,29 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
will(returnValue(authorName)); will(returnValue(authorName));
oneOf(setupActivity).getPassword(); oneOf(setupActivity).getPassword();
will(returnValue(password)); will(returnValue(password));
// Create and register the local author
oneOf(identityManager).createLocalAuthor(authorName);
will(returnValue(localAuthor));
oneOf(identityManager).registerLocalAuthor(localAuthor);
// Generate a database key // Generate a database key
oneOf(crypto).generateSecretKey(); oneOf(crypto).generateSecretKey();
will(returnValue(key)); will(returnValue(key));
// Attach the author name and database key to the database config
oneOf(databaseConfig).setLocalAuthorName(authorName);
oneOf(databaseConfig).setEncryptionKey(key);
// Encrypt the key with the password // Encrypt the key with the password
oneOf(crypto).encryptWithPassword(key.getBytes(), password); oneOf(crypto).encryptWithPassword(key.getBytes(), password);
will(returnValue(encryptedKey)); will(returnValue(encryptedKey));
// Store the encrypted key // Store the encrypted key
allowing(databaseConfig).getDatabaseKeyDirectory(); allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir)); will(returnValue(keyDir));
// Attach the database key to the database config
oneOf(databaseConfig).setEncryptionKey(key);
}}); }});
assertFalse(keyFile.exists()); assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists()); assertFalse(keyBackupFile.exists());
SetupControllerImpl s = new SetupControllerImpl(briarPrefs, SetupControllerImpl s = new SetupControllerImpl(briarPrefs,
databaseConfig, cryptoExecutor, crypto, estimator); databaseConfig, cryptoExecutor, crypto, estimator,
identityManager);
s.setSetupActivity(setupActivity); s.setSetupActivity(setupActivity);
AtomicBoolean called = new AtomicBoolean(false); AtomicBoolean called = new AtomicBoolean(false);
@@ -103,8 +113,10 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
assertTrue(keyFile.exists()); assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists()); assertTrue(keyBackupFile.exists());
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile)); assertEquals(toHexString(encryptedKey),
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyBackupFile)); loadDatabaseKey(keyFile));
assertEquals(toHexString(encryptedKey),
loadDatabaseKey(keyBackupFile));
} }
@After @After

View File

@@ -1,5 +1,7 @@
package org.briarproject.briar.feed; package org.briarproject.briar.feed;
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;
@@ -47,8 +49,12 @@ public class FeedManagerIntegrationTest extends BriarTestCase {
component.inject(this); component.inject(this);
injectEagerSingletons(component); injectEagerSingletons(component);
IdentityManager identityManager = component.getIdentityManager();
LocalAuthor localAuthor = identityManager.createLocalAuthor("feedTest");
identityManager.registerLocalAuthor(localAuthor);
lifecycleManager = component.getLifecycleManager(); lifecycleManager = component.getLifecycleManager();
lifecycleManager.startServices("feedTest"); lifecycleManager.startServices();
lifecycleManager.waitForStartup(); lifecycleManager.waitForStartup();
feedManager = component.getFeedManager(); feedManager = component.getFeedManager();

View File

@@ -1,5 +1,6 @@
package org.briarproject.briar.feed; package org.briarproject.briar.feed;
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.client.ClientModule; import org.briarproject.bramble.client.ClientModule;
import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.contact.ContactModule;
@@ -76,6 +77,8 @@ interface FeedManagerIntegrationTestComponent {
void inject(VersioningModule.EagerSingletons init); void inject(VersioningModule.EagerSingletons init);
IdentityManager getIdentityManager();
LifecycleManager getLifecycleManager(); LifecycleManager getLifecycleManager();
FeedManager getFeedManager(); FeedManager getFeedManager();

View File

@@ -44,7 +44,6 @@ import java.io.InputStream;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.test.TestPluginConfigModule.MAX_LATENCY; import static org.briarproject.bramble.test.TestPluginConfigModule.MAX_LATENCY;
import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID; import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
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;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -58,8 +57,6 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
private final File bobDir = new File(testDir, "bob"); private final File bobDir = new File(testDir, "bob");
private final SecretKey master = getSecretKey(); private final SecretKey master = getSecretKey();
private final long timestamp = System.currentTimeMillis(); private final long timestamp = System.currentTimeMillis();
private final LocalAuthor aliceAuthor = getLocalAuthor();
private final LocalAuthor bobAuthor = getLocalAuthor();
private SimplexMessagingIntegrationTestComponent alice, bob; private SimplexMessagingIntegrationTestComponent alice, bob;
@@ -76,6 +73,11 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
@Test @Test
public void testWriteAndRead() throws Exception { public void testWriteAndRead() throws Exception {
// Create the identities
LocalAuthor aliceAuthor =
alice.getIdentityManager().createLocalAuthor("Alice");
LocalAuthor bobAuthor =
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, aliceAuthor, bobAuthor, true);
ContactId aliceId = setUp(bob, bobAuthor, aliceAuthor, false); ContactId aliceId = setUp(bob, bobAuthor, aliceAuthor, false);
@@ -98,13 +100,13 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
private ContactId setUp(SimplexMessagingIntegrationTestComponent device, private ContactId setUp(SimplexMessagingIntegrationTestComponent device,
LocalAuthor local, Author remote, boolean alice) throws Exception { LocalAuthor local, Author remote, boolean alice) throws Exception {
// Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices(null);
lifecycleManager.waitForStartup();
// Add an identity for the user // Add an identity for the user
IdentityManager identityManager = device.getIdentityManager(); IdentityManager identityManager = device.getIdentityManager();
identityManager.registerLocalAuthor(local); identityManager.registerLocalAuthor(local);
// Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices();
lifecycleManager.waitForStartup();
// Add the other user as a contact // Add the other user as a contact
ContactManager contactManager = device.getContactManager(); ContactManager contactManager = device.getContactManager();
return contactManager.addContact(remote, local.getId(), master, return contactManager.addContact(remote, local.getId(), master,

View File

@@ -160,8 +160,8 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
validationWaiter = new Waiter(); validationWaiter = new Waiter();
deliveryWaiter = new Waiter(); deliveryWaiter = new Waiter();
createAndRegisterIdentities();
startLifecycles(); startLifecycles();
getDefaultIdentities();
listenToEvents(); listenToEvents();
addDefaultContacts(); addDefaultContacts();
} }
@@ -193,9 +193,9 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
lifecycleManager0 = c0.getLifecycleManager(); lifecycleManager0 = c0.getLifecycleManager();
lifecycleManager1 = c1.getLifecycleManager(); lifecycleManager1 = c1.getLifecycleManager();
lifecycleManager2 = c2.getLifecycleManager(); lifecycleManager2 = c2.getLifecycleManager();
lifecycleManager0.startServices(AUTHOR0); lifecycleManager0.startServices();
lifecycleManager1.startServices(AUTHOR1); lifecycleManager1.startServices();
lifecycleManager2.startServices(AUTHOR2); lifecycleManager2.startServices();
lifecycleManager0.waitForStartup(); lifecycleManager0.waitForStartup();
lifecycleManager1.waitForStartup(); lifecycleManager1.waitForStartup();
lifecycleManager2.waitForStartup(); lifecycleManager2.waitForStartup();
@@ -230,10 +230,13 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
} }
} }
private void getDefaultIdentities() throws DbException { private void createAndRegisterIdentities() {
author0 = identityManager0.getLocalAuthor(); author0 = identityManager0.createLocalAuthor(AUTHOR0);
author1 = identityManager1.getLocalAuthor(); identityManager0.registerLocalAuthor(author0);
author2 = identityManager2.getLocalAuthor(); author1 = identityManager1.createLocalAuthor(AUTHOR1);
identityManager1.registerLocalAuthor(author1);
author2 = identityManager2.createLocalAuthor(AUTHOR2);
identityManager2.registerLocalAuthor(author2);
} }
protected void addDefaultContacts() throws Exception { protected void addDefaultContacts() throws Exception {