mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Merge branch '1341-account-manager-refactoring' into 'master'
Refactor authentication and account management code Closes #1341 See merge request briar/briar!866
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package org.briarproject.bramble.account;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.Localizer;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
class BriarAccountManager extends AndroidAccountManager {
|
||||
|
||||
@Inject
|
||||
BriarAccountManager(DatabaseConfig databaseConfig, CryptoComponent crypto,
|
||||
IdentityManager identityManager, SharedPreferences prefs,
|
||||
Application app) {
|
||||
super(databaseConfig, crypto, identityManager, prefs, app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAccount() {
|
||||
synchronized (stateChangeLock) {
|
||||
super.deleteAccount();
|
||||
Localizer.reinitialize();
|
||||
UiUtils.setTheme(appContext,
|
||||
appContext.getString(R.string.pref_theme_light_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.bramble.account;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class BriarAccountModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
AccountManager provideAccountManager(BriarAccountManager accountManager) {
|
||||
return accountManager;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.briarproject.bramble.BrambleAndroidModule;
|
||||
import org.briarproject.bramble.BrambleCoreEagerSingletons;
|
||||
import org.briarproject.bramble.BrambleCoreModule;
|
||||
import org.briarproject.bramble.account.BriarAccountModule;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.contact.ContactExchangeTask;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
@@ -62,6 +60,7 @@ import dagger.Component;
|
||||
BrambleCoreModule.class,
|
||||
BriarCoreModule.class,
|
||||
BrambleAndroidModule.class,
|
||||
BriarAccountModule.class,
|
||||
AppModule.class
|
||||
})
|
||||
public interface AndroidComponent
|
||||
@@ -73,10 +72,6 @@ public interface AndroidComponent
|
||||
|
||||
PasswordStrengthEstimator passwordStrengthIndicator();
|
||||
|
||||
CryptoComponent cryptoComponent();
|
||||
|
||||
DatabaseConfig databaseConfig();
|
||||
|
||||
@DatabaseExecutor
|
||||
Executor databaseExecutor();
|
||||
|
||||
@@ -92,8 +87,6 @@ public interface AndroidComponent
|
||||
|
||||
AndroidNotificationManager androidNotificationManager();
|
||||
|
||||
SharedPreferences sharedPreferences();
|
||||
|
||||
ScreenFilterMonitor screenFilterMonitor();
|
||||
|
||||
ConnectionRegistry connectionRegistry();
|
||||
@@ -151,6 +144,8 @@ public interface AndroidComponent
|
||||
@IoExecutor
|
||||
Executor ioExecutor();
|
||||
|
||||
AccountManager accountManager();
|
||||
|
||||
void inject(SignInReminderReceiver briarService);
|
||||
|
||||
void inject(BriarService briarService);
|
||||
|
||||
@@ -1,99 +1,30 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
|
||||
@NotNullByDefault
|
||||
class AndroidDatabaseConfig implements DatabaseConfig {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(AndroidDatabaseConfig.class.getName());
|
||||
|
||||
private final File dbDir, keyDir;
|
||||
|
||||
@Nullable
|
||||
private volatile SecretKey key = null;
|
||||
@Nullable
|
||||
private volatile String nickname = null;
|
||||
|
||||
AndroidDatabaseConfig(File dbDir, File keyDir) {
|
||||
this.dbDir = dbDir;
|
||||
this.keyDir = keyDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean databaseExists() {
|
||||
// FIXME should not run on UiThread #620
|
||||
if (!dbDir.isDirectory()) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(dbDir.getAbsolutePath() + " is not a directory");
|
||||
return false;
|
||||
}
|
||||
File[] files = dbDir.listFiles();
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
if (files == null) {
|
||||
LOG.info("Could not list files in " + dbDir.getAbsolutePath());
|
||||
} else {
|
||||
LOG.info("Files in " + dbDir.getAbsolutePath() + ":");
|
||||
for (File f : files) LOG.info(f.getName());
|
||||
}
|
||||
LOG.info("Database exists: " + (files != null && files.length > 0));
|
||||
}
|
||||
return files != null && files.length > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDatabaseDirectory() {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Database directory: " + dbDir.getAbsolutePath());
|
||||
return dbDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDatabaseKeyDirectory() {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Database key directory: " + keyDir.getAbsolutePath());
|
||||
return keyDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEncryptionKey(SecretKey key) {
|
||||
LOG.info("Setting database 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
|
||||
@Nullable
|
||||
public SecretKey getEncryptionKey() {
|
||||
SecretKey key = this.key;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Database key has been set: " + (key != null));
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxSize() {
|
||||
return Long.MAX_VALUE;
|
||||
|
||||
@@ -11,9 +11,7 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
@@ -86,11 +84,7 @@ public class AppModule {
|
||||
File dbDir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
|
||||
File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE);
|
||||
StrictMode.setThreadPolicy(tp);
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
DatabaseConfig databaseConfig =
|
||||
new AndroidDatabaseConfig(dbDir, keyDir);
|
||||
return databaseConfig;
|
||||
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -17,7 +17,8 @@ import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
@@ -74,12 +75,13 @@ public class BriarService extends Service {
|
||||
private BroadcastReceiver receiver = null;
|
||||
|
||||
@Inject
|
||||
protected DatabaseConfig databaseConfig;
|
||||
AccountManager accountManager;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
protected volatile LifecycleManager lifecycleManager;
|
||||
volatile LifecycleManager lifecycleManager;
|
||||
@Inject
|
||||
protected volatile AndroidExecutor androidExecutor;
|
||||
volatile AndroidExecutor androidExecutor;
|
||||
private volatile boolean started = false;
|
||||
|
||||
@Override
|
||||
@@ -95,7 +97,8 @@ public class BriarService extends Service {
|
||||
stopSelf();
|
||||
return;
|
||||
}
|
||||
if (databaseConfig.getEncryptionKey() == null) {
|
||||
SecretKey dbKey = accountManager.getDatabaseKey();
|
||||
if (dbKey == null) {
|
||||
LOG.info("No database key");
|
||||
stopSelf();
|
||||
return;
|
||||
@@ -138,8 +141,7 @@ public class BriarService extends Service {
|
||||
startForeground(ONGOING_NOTIFICATION_ID, b.build());
|
||||
// Start the services in a background thread
|
||||
new Thread(() -> {
|
||||
String nickname = databaseConfig.getLocalAuthorName();
|
||||
StartResult result = lifecycleManager.startServices(nickname);
|
||||
StartResult result = lifecycleManager.startServices(dbKey);
|
||||
if (result == SUCCESS) {
|
||||
started = true;
|
||||
} else if (result == ALREADY_RUNNING) {
|
||||
|
||||
@@ -4,8 +4,6 @@ import android.app.Activity;
|
||||
|
||||
import org.briarproject.briar.android.controller.BriarController;
|
||||
import org.briarproject.briar.android.controller.BriarControllerImpl;
|
||||
import org.briarproject.briar.android.controller.ConfigController;
|
||||
import org.briarproject.briar.android.controller.ConfigControllerImpl;
|
||||
import org.briarproject.briar.android.controller.DbController;
|
||||
import org.briarproject.briar.android.controller.DbControllerImpl;
|
||||
import org.briarproject.briar.android.login.PasswordController;
|
||||
@@ -48,13 +46,6 @@ public class ActivityModule {
|
||||
return setupController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
ConfigController provideConfigController(
|
||||
ConfigControllerImpl configController) {
|
||||
return configController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
PasswordController providePasswordController(
|
||||
|
||||
@@ -61,7 +61,7 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (!briarController.hasEncryptionKey() && !isFinishing()) {
|
||||
if (!briarController.accountSignedIn() && !isFinishing()) {
|
||||
Intent i = new Intent(this, PasswordActivity.class);
|
||||
startActivityForResult(i, REQUEST_PASSWORD);
|
||||
} else if (SDK_INT >= 23) {
|
||||
@@ -138,7 +138,7 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
protected void signOut(boolean removeFromRecentApps) {
|
||||
if (briarController.hasEncryptionKey()) {
|
||||
if (briarController.accountSignedIn()) {
|
||||
// Don't use UiResultHandler because we want the result even if
|
||||
// this activity has been destroyed
|
||||
briarController.signOut(result -> runOnUiThread(
|
||||
|
||||
@@ -6,7 +6,7 @@ public interface BriarController extends ActivityLifecycleController {
|
||||
|
||||
void startAndBindService();
|
||||
|
||||
boolean hasEncryptionKey();
|
||||
boolean accountSignedIn();
|
||||
|
||||
/**
|
||||
* Returns true via the handler when the app has dozed
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.CallSuper;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.settings.Settings;
|
||||
@@ -33,8 +33,7 @@ public class BriarControllerImpl implements BriarController {
|
||||
public static final String DOZE_ASK_AGAIN = "dozeAskAgain";
|
||||
|
||||
private final BriarServiceConnection serviceConnection;
|
||||
private final DatabaseConfig databaseConfig;
|
||||
@DatabaseExecutor
|
||||
private final AccountManager accountManager;
|
||||
private final Executor databaseExecutor;
|
||||
private final SettingsManager settingsManager;
|
||||
private final DozeWatchdog dozeWatchdog;
|
||||
@@ -44,12 +43,12 @@ public class BriarControllerImpl implements BriarController {
|
||||
|
||||
@Inject
|
||||
BriarControllerImpl(BriarServiceConnection serviceConnection,
|
||||
DatabaseConfig databaseConfig,
|
||||
AccountManager accountManager,
|
||||
@DatabaseExecutor Executor databaseExecutor,
|
||||
SettingsManager settingsManager, DozeWatchdog dozeWatchdog,
|
||||
Activity activity) {
|
||||
this.serviceConnection = serviceConnection;
|
||||
this.databaseConfig = databaseConfig;
|
||||
this.accountManager = accountManager;
|
||||
this.databaseExecutor = databaseExecutor;
|
||||
this.settingsManager = settingsManager;
|
||||
this.dozeWatchdog = dozeWatchdog;
|
||||
@@ -59,7 +58,7 @@ public class BriarControllerImpl implements BriarController {
|
||||
@Override
|
||||
@CallSuper
|
||||
public void onActivityCreate(Activity activity) {
|
||||
if (databaseConfig.getEncryptionKey() != null) startAndBindService();
|
||||
if (accountManager.hasDatabaseKey()) startAndBindService();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,8 +83,8 @@ public class BriarControllerImpl implements BriarController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEncryptionKey() {
|
||||
return databaseConfig.getEncryptionKey() != null;
|
||||
public boolean accountSignedIn() {
|
||||
return accountManager.hasDatabaseKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.briarproject.briar.android.controller;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface ConfigController {
|
||||
|
||||
@Nullable
|
||||
String getEncryptedDatabaseKey();
|
||||
|
||||
boolean storeEncryptedDatabaseKey(String hex);
|
||||
|
||||
void deleteAccount(Context ctx);
|
||||
|
||||
boolean accountExists();
|
||||
|
||||
boolean accountSignedIn();
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package org.briarproject.briar.android.controller;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
public class ConfigControllerImpl implements ConfigController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ConfigControllerImpl.class.getName());
|
||||
|
||||
private static final String PREF_DB_KEY = "key";
|
||||
private static final String DB_KEY_FILENAME = "db.key";
|
||||
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
|
||||
|
||||
private final SharedPreferences briarPrefs;
|
||||
private final File dbKeyFile, dbKeyBackupFile;
|
||||
protected final DatabaseConfig databaseConfig;
|
||||
|
||||
@Inject
|
||||
public ConfigControllerImpl(SharedPreferences briarPrefs,
|
||||
DatabaseConfig databaseConfig) {
|
||||
this.briarPrefs = briarPrefs;
|
||||
this.databaseConfig = databaseConfig;
|
||||
File keyDir = databaseConfig.getDatabaseKeyDirectory();
|
||||
dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
|
||||
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getEncryptedDatabaseKey() {
|
||||
String key = getDatabaseKeyFromPreferences();
|
||||
if (key == null) key = getDatabaseKeyFromFile();
|
||||
else migrateDatabaseKeyToFile(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getDatabaseKeyFromPreferences() {
|
||||
String key = briarPrefs.getString(PREF_DB_KEY, null);
|
||||
if (key == null) LOG.info("No database key in preferences");
|
||||
else LOG.info("Found database key in preferences");
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getDatabaseKeyFromFile() {
|
||||
String key = readDbKeyFromFile(dbKeyFile);
|
||||
if (key == null) {
|
||||
LOG.info("No database key in primary file");
|
||||
key = readDbKeyFromFile(dbKeyBackupFile);
|
||||
if (key == null) LOG.info("No database key in backup file");
|
||||
else LOG.warning("Found database key in backup file");
|
||||
} else {
|
||||
LOG.info("Found database key in primary file");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String readDbKeyFromFile(File f) {
|
||||
if (!f.exists()) {
|
||||
LOG.info("Key file does not exist");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(f), "UTF-8"));
|
||||
String key = reader.readLine();
|
||||
reader.close();
|
||||
return key;
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void migrateDatabaseKeyToFile(String key) {
|
||||
if (storeEncryptedDatabaseKey(key)) {
|
||||
if (briarPrefs.edit().remove(PREF_DB_KEY).commit())
|
||||
LOG.info("Database key migrated to file");
|
||||
else LOG.warning("Database key not removed from preferences");
|
||||
} else {
|
||||
LOG.warning("Database key not migrated to file");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean storeEncryptedDatabaseKey(String hex) {
|
||||
LOG.info("Storing database key in file");
|
||||
// Create the directory if necessary
|
||||
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
|
||||
LOG.info("Created database key directory");
|
||||
// If only the backup file exists, rename it so we don't overwrite it
|
||||
if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) {
|
||||
if (dbKeyBackupFile.renameTo(dbKeyFile))
|
||||
LOG.info("Renamed old backup");
|
||||
else LOG.warning("Failed to rename old backup");
|
||||
}
|
||||
try {
|
||||
// Write to the backup file
|
||||
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||
LOG.info("Stored database key in backup file");
|
||||
// Delete the old primary file, if it exists
|
||||
if (dbKeyFile.exists()) {
|
||||
if (dbKeyFile.delete()) LOG.info("Deleted primary file");
|
||||
else LOG.warning("Failed to delete primary file");
|
||||
}
|
||||
// The backup file becomes the new primary
|
||||
if (dbKeyBackupFile.renameTo(dbKeyFile)) {
|
||||
LOG.info("Renamed backup file to primary");
|
||||
} else {
|
||||
LOG.warning("Failed to rename backup file to primary");
|
||||
return false; // Don't overwrite our only copy
|
||||
}
|
||||
// Write a second copy to the backup file
|
||||
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||
LOG.info("Stored second copy of database key in backup file");
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDbKeyToFile(String key, File f) throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(f);
|
||||
out.write(key.getBytes("UTF-8"));
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAccount(Context ctx) {
|
||||
LOG.info("Deleting account");
|
||||
SharedPreferences defaultPrefs =
|
||||
PreferenceManager.getDefaultSharedPreferences(ctx);
|
||||
AndroidUtils.deleteAppData(ctx, briarPrefs, defaultPrefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accountExists() {
|
||||
String hex = getEncryptedDatabaseKey();
|
||||
return hex != null && databaseConfig.databaseExists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accountSignedIn() {
|
||||
return databaseConfig.getEncryptionKey() != null;
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.Localizer;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BaseActivity;
|
||||
import org.briarproject.briar.android.controller.BriarController;
|
||||
@@ -33,6 +33,9 @@ import static org.briarproject.briar.api.android.AndroidNotificationManager.REMI
|
||||
|
||||
public class PasswordActivity extends BaseActivity {
|
||||
|
||||
@Inject
|
||||
AccountManager accountManager;
|
||||
|
||||
@Inject
|
||||
PasswordController passwordController;
|
||||
|
||||
@@ -50,7 +53,8 @@ public class PasswordActivity extends BaseActivity {
|
||||
// fade-in after splash screen instead of default animation
|
||||
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
|
||||
|
||||
if (!passwordController.accountExists()) {
|
||||
if (!accountManager.accountExists()) {
|
||||
// TODO: Finish instead of deleting account?
|
||||
deleteAccount();
|
||||
return;
|
||||
}
|
||||
@@ -87,7 +91,7 @@ public class PasswordActivity extends BaseActivity {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
// If the user has already signed in, clean up this instance
|
||||
if (briarController.hasEncryptionKey()) {
|
||||
if (briarController.accountSignedIn()) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} else {
|
||||
@@ -112,9 +116,7 @@ public class PasswordActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void deleteAccount() {
|
||||
passwordController.deleteAccount(this);
|
||||
Localizer.reinitialize();
|
||||
UiUtils.setTheme(this, getString(R.string.pref_theme_light_value));
|
||||
accountManager.deleteAccount();
|
||||
setResult(RESULT_CANCELED);
|
||||
Intent i = new Intent(this, SetupActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.android.controller.ConfigController;
|
||||
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface PasswordController extends ConfigController {
|
||||
public interface PasswordController {
|
||||
|
||||
float estimatePasswordStrength(String password);
|
||||
|
||||
void validatePassword(String password,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
void changePassword(String password, String newPassword,
|
||||
void changePassword(String oldPassword, String newPassword,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,44 +1,28 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.android.controller.ConfigControllerImpl;
|
||||
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||
import static org.briarproject.bramble.util.LogUtils.now;
|
||||
|
||||
@NotNullByDefault
|
||||
public class PasswordControllerImpl extends ConfigControllerImpl
|
||||
implements PasswordController {
|
||||
public class PasswordControllerImpl implements PasswordController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(PasswordControllerImpl.class.getName());
|
||||
|
||||
protected final Executor cryptoExecutor;
|
||||
protected final CryptoComponent crypto;
|
||||
protected final AccountManager accountManager;
|
||||
protected final Executor ioExecutor;
|
||||
private final PasswordStrengthEstimator strengthEstimator;
|
||||
|
||||
@Inject
|
||||
PasswordControllerImpl(SharedPreferences briarPrefs,
|
||||
DatabaseConfig databaseConfig,
|
||||
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
|
||||
PasswordControllerImpl(AccountManager accountManager,
|
||||
@IoExecutor Executor ioExecutor,
|
||||
PasswordStrengthEstimator strengthEstimator) {
|
||||
super(briarPrefs, databaseConfig);
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.crypto = crypto;
|
||||
this.accountManager = accountManager;
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.strengthEstimator = strengthEstimator;
|
||||
}
|
||||
|
||||
@@ -50,46 +34,17 @@ public class PasswordControllerImpl extends ConfigControllerImpl
|
||||
@Override
|
||||
public void validatePassword(String password,
|
||||
ResultHandler<Boolean> resultHandler) {
|
||||
byte[] encrypted = getEncryptedKey();
|
||||
cryptoExecutor.execute(() -> {
|
||||
byte[] key = crypto.decryptWithPassword(encrypted, password);
|
||||
if (key == null) {
|
||||
resultHandler.onResult(false);
|
||||
} else {
|
||||
databaseConfig.setEncryptionKey(new SecretKey(key));
|
||||
resultHandler.onResult(true);
|
||||
}
|
||||
});
|
||||
ioExecutor.execute(() ->
|
||||
resultHandler.onResult(accountManager.signIn(password)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changePassword(String password, String newPassword,
|
||||
public void changePassword(String oldPassword, String newPassword,
|
||||
ResultHandler<Boolean> resultHandler) {
|
||||
byte[] encrypted = getEncryptedKey();
|
||||
cryptoExecutor.execute(() -> {
|
||||
byte[] key = crypto.decryptWithPassword(encrypted, password);
|
||||
if (key == null) {
|
||||
resultHandler.onResult(false);
|
||||
} else {
|
||||
String hex =
|
||||
encryptDatabaseKey(new SecretKey(key), newPassword);
|
||||
resultHandler.onResult(storeEncryptedDatabaseKey(hex));
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
boolean changed =
|
||||
accountManager.changePassword(oldPassword, newPassword);
|
||||
resultHandler.onResult(changed);
|
||||
});
|
||||
}
|
||||
|
||||
private byte[] getEncryptedKey() {
|
||||
String hex = getEncryptedDatabaseKey();
|
||||
if (hex == null)
|
||||
throw new IllegalStateException("Encrypted database key is null");
|
||||
return StringUtils.fromHexString(hex);
|
||||
}
|
||||
|
||||
@CryptoExecutor
|
||||
String encryptDatabaseKey(SecretKey key, String password) {
|
||||
long start = now();
|
||||
byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
|
||||
logDuration(LOG, "Key derivation", start);
|
||||
return StringUtils.toHexString(encrypted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
@@ -25,6 +26,9 @@ public class SetupActivity extends BaseActivity
|
||||
private static final String STATE_KEY_AUTHOR_NAME = "authorName";
|
||||
private static final String STATE_KEY_PASSWORD = "password";
|
||||
|
||||
@Inject
|
||||
AccountManager accountManager;
|
||||
|
||||
@Inject
|
||||
SetupController setupController;
|
||||
|
||||
@@ -39,8 +43,7 @@ public class SetupActivity extends BaseActivity
|
||||
setContentView(R.layout.activity_fragment_container);
|
||||
|
||||
if (state == null) {
|
||||
if (setupController.accountExists())
|
||||
throw new AssertionError();
|
||||
if (accountManager.accountExists()) throw new AssertionError();
|
||||
showInitialFragment(AuthorNameFragment.newInstance());
|
||||
} else {
|
||||
authorName = state.getString(STATE_KEY_AUTHOR_NAME);
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
import org.briarproject.briar.android.controller.handler.UiResultHandler;
|
||||
@@ -28,12 +25,10 @@ public class SetupControllerImpl extends PasswordControllerImpl
|
||||
private volatile SetupActivity setupActivity;
|
||||
|
||||
@Inject
|
||||
SetupControllerImpl(SharedPreferences briarPrefs,
|
||||
DatabaseConfig databaseConfig,
|
||||
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
|
||||
SetupControllerImpl(AccountManager accountManager,
|
||||
@IoExecutor Executor ioExecutor,
|
||||
PasswordStrengthEstimator strengthEstimator) {
|
||||
super(briarPrefs, databaseConfig, cryptoExecutor, crypto,
|
||||
strengthEstimator);
|
||||
super(accountManager, ioExecutor, strengthEstimator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,10 +75,11 @@ public class SetupControllerImpl extends PasswordControllerImpl
|
||||
@Override
|
||||
public void createAccount() {
|
||||
SetupActivity setupActivity = this.setupActivity;
|
||||
UiResultHandler<Void> resultHandler =
|
||||
new UiResultHandler<Void>(setupActivity) {
|
||||
UiResultHandler<Boolean> resultHandler =
|
||||
new UiResultHandler<Boolean>(setupActivity) {
|
||||
@Override
|
||||
public void onResultUi(Void result) {
|
||||
public void onResultUi(Boolean result) {
|
||||
// TODO: Show an error if result is false
|
||||
if (setupActivity == null)
|
||||
throw new IllegalStateException();
|
||||
setupActivity.showApp();
|
||||
@@ -93,22 +89,17 @@ public class SetupControllerImpl extends PasswordControllerImpl
|
||||
}
|
||||
|
||||
// Package access for testing
|
||||
void createAccount(ResultHandler<Void> resultHandler) {
|
||||
void createAccount(ResultHandler<Boolean> resultHandler) {
|
||||
SetupActivity setupActivity = this.setupActivity;
|
||||
if (setupActivity == null) throw new IllegalStateException();
|
||||
String authorName = setupActivity.getAuthorName();
|
||||
if (authorName == null) throw new IllegalStateException();
|
||||
String password = setupActivity.getPassword();
|
||||
if (password == null) throw new IllegalStateException();
|
||||
cryptoExecutor.execute(() -> {
|
||||
ioExecutor.execute(() -> {
|
||||
LOG.info("Creating account");
|
||||
databaseConfig.setLocalAuthorName(authorName);
|
||||
SecretKey key = crypto.generateSecretKey();
|
||||
databaseConfig.setEncryptionKey(key);
|
||||
String hex = encryptDatabaseKey(key, password);
|
||||
storeEncryptedDatabaseKey(hex);
|
||||
resultHandler.onResult(null);
|
||||
resultHandler.onResult(accountManager.createAccount(authorName,
|
||||
password));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import android.content.SharedPreferences;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.AndroidComponent;
|
||||
import org.briarproject.briar.android.BriarApplication;
|
||||
@@ -37,7 +37,7 @@ public class SignInReminderReceiver extends BroadcastReceiver {
|
||||
public static final String DISMISS_REMINDER = "dismissReminder";
|
||||
|
||||
@Inject
|
||||
DatabaseConfig databaseConfig;
|
||||
AccountManager accountManager;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
@@ -51,7 +51,7 @@ public class SignInReminderReceiver extends BroadcastReceiver {
|
||||
if (action == null) return;
|
||||
if (action.equals(ACTION_BOOT_COMPLETED) ||
|
||||
action.equals(ACTION_MY_PACKAGE_REPLACED)) {
|
||||
if (databaseConfig.databaseExists()) {
|
||||
if (accountManager.accountExists()) {
|
||||
SharedPreferences prefs = app.getDefaultSharedPreferences();
|
||||
if (prefs.getBoolean(NOTIFY_SIGN_IN, true)) {
|
||||
showSignInNotification(ctx);
|
||||
|
||||
@@ -7,10 +7,10 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.controller.ConfigController;
|
||||
import org.iilab.IilabEngineeringRSA2048Pin;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
@@ -33,7 +33,7 @@ public class PanicResponderActivity extends BriarActivity {
|
||||
Logger.getLogger(PanicResponderActivity.class.getName());
|
||||
|
||||
@Inject
|
||||
protected ConfigController configController;
|
||||
protected AccountManager accountManager;
|
||||
@Inject
|
||||
protected AndroidExecutor androidExecutor;
|
||||
|
||||
@@ -94,7 +94,7 @@ public class PanicResponderActivity extends BriarActivity {
|
||||
|
||||
private void deleteAllData() {
|
||||
androidExecutor.runOnBackgroundThread(() -> {
|
||||
configController.deleteAccount(PanicResponderActivity.this);
|
||||
accountManager.deleteAccount();
|
||||
// TODO somehow delete/shred the database more thoroughly
|
||||
PanicResponder.deleteAllAppData(PanicResponderActivity.this);
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ import android.os.Handler;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.transition.Fade;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BaseActivity;
|
||||
import org.briarproject.briar.android.controller.ConfigController;
|
||||
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
Logger.getLogger(SplashScreenActivity.class.getName());
|
||||
|
||||
@Inject
|
||||
protected ConfigController configController;
|
||||
protected AccountManager accountManager;
|
||||
@Inject
|
||||
protected AndroidExecutor androidExecutor;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
setContentView(R.layout.splash);
|
||||
|
||||
if (configController.accountSignedIn()) {
|
||||
if (accountManager.hasDatabaseKey()) {
|
||||
startActivity(new Intent(this, OpenDatabaseActivity.class));
|
||||
finish();
|
||||
} else {
|
||||
@@ -64,12 +64,12 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
LOG.info("Expired");
|
||||
startActivity(new Intent(this, ExpiredActivity.class));
|
||||
} else {
|
||||
if (configController.accountExists()) {
|
||||
if (accountManager.accountExists()) {
|
||||
LOG.info("Account exists");
|
||||
startActivity(new Intent(this, OpenDatabaseActivity.class));
|
||||
} else {
|
||||
LOG.info("Account does not exist");
|
||||
configController.deleteAccount(this);
|
||||
accountManager.deleteAccount();
|
||||
startActivity(new Intent(this, SetupActivity.class));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user