Skip to content

fix: ensure drive keys are properly cleared during logout #1997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/authentication/ardrive_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ abstract class ArDriveAuth {
required SecureKeyValueStore secureKeyValueStore,
required ArConnectService arConnectService,
required DatabaseHelpers databaseHelpers,
required DriveDao driveDao,
MetadataCache? metadataCache,
}) =>
ArDriveAuthImpl(
Expand All @@ -57,6 +58,7 @@ abstract class ArDriveAuth {
secureKeyValueStore: secureKeyValueStore,
arConnectService: arConnectService,
metadataCache: metadataCache,
driveDao: driveDao,
);
}

Expand All @@ -69,10 +71,12 @@ class ArDriveAuthImpl implements ArDriveAuth {
required SecureKeyValueStore secureKeyValueStore,
required ArConnectService arConnectService,
required DatabaseHelpers databaseHelpers,
required DriveDao driveDao,
MetadataCache? metadataCache,
}) : _arweave = arweave,
_crypto = crypto,
_databaseHelpers = databaseHelpers,
_driveDao = driveDao,
_arConnectService = arConnectService,
_secureKeyValueStore = secureKeyValueStore,
_biometricAuthentication = biometricAuthentication,
Expand All @@ -86,6 +90,7 @@ class ArDriveAuthImpl implements ArDriveAuth {
final SecureKeyValueStore _secureKeyValueStore;
final ArConnectService _arConnectService;
final DatabaseHelpers _databaseHelpers;
final DriveDao _driveDao;
MetadataCache? _maybeMetadataCache;

User? _currentUser;
Expand Down Expand Up @@ -266,6 +271,7 @@ class ArDriveAuthImpl implements ArDriveAuth {
}

await _databaseHelpers.deleteAllTables();
await _driveDao.removeAllDriveKeys();
currentUser = null;
_userStreamController.add(null);
} catch (e, stacktrace) {
Expand Down
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ class AppState extends State<App> {
),
RepositoryProvider(
create: (context) => ArDriveAuth(
driveDao: context.read<DriveDao>(),
databaseHelpers: DatabaseHelpers(
context.read<Database>(),
),
Expand Down
9 changes: 9 additions & 0 deletions lib/models/daos/drive_dao/drive_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ class DriveDao extends DatabaseAccessor<Database> with _$DriveDaoMixin {
_previewVault = await store.vault<Uint8List>(name: 'previewVault');
}

Future<void> removeAllDriveKeys() async {
try {
logger.i('Removing all drive keys');
await _driveKeyVault.clear();
} catch (e) {
throw _handleError('Error removing all drive keys', e);
}
}

Future<void> deleteSharedPrivateDrives(String? owner) async {
try {
final drives = (await allDrives().get()).where(
Expand Down
12 changes: 7 additions & 5 deletions lib/models/database/database_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class DatabaseHelpers {
Future<void> deleteAllTables() async {
try {
logger.d('Deleting all tables');
await _db.transaction(() async {
for (final table in _db.allTables) {
await _db.delete(table).go();
}
});
await _db.transaction(
() async {
for (final table in _db.allTables) {
await _db.delete(table).go();
}
},
);
} catch (e) {
logger.e('Error deleting all tables', e);
}
Expand Down
16 changes: 14 additions & 2 deletions test/authentication/ardrive_auth_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ void main() {
late MockSecureKeyValueStore mockSecureKeyValueStore;
late MockArConnectService mockArConnectService;
late MockDatabaseHelpers mockDatabaseHelpers;

late MockDriveDao mockDriveDao;
final wallet = getTestWallet();

setUp(() async {
Expand All @@ -36,6 +36,7 @@ void main() {
mockSecureKeyValueStore = MockSecureKeyValueStore();
mockArConnectService = MockArConnectService();
mockDatabaseHelpers = MockDatabaseHelpers();
mockDriveDao = MockDriveDao();

final metadataCache = await MetadataCache.fromCacheStore(
await newMemoryCacheStore(),
Expand All @@ -50,6 +51,7 @@ void main() {
biometricAuthentication: mockBiometricAuthentication,
secureKeyValueStore: mockSecureKeyValueStore,
metadataCache: metadataCache,
driveDao: mockDriveDao,
);

registerFallbackValue(DriveEntity(
Expand Down Expand Up @@ -583,6 +585,8 @@ void main() {
.thenAnswer((invocation) => Future.value(true));
when(() => mockDatabaseHelpers.deleteAllTables())
.thenAnswer((invocation) async {});
when(() => mockDriveDao.removeAllDriveKeys())
.thenAnswer((invocation) async {});

await arDriveAuth.logout();

Expand All @@ -592,6 +596,7 @@ void main() {
verify(() => mockSecureKeyValueStore.remove('biometricEnabled'))
.called(1);
verify(() => mockDatabaseHelpers.deleteAllTables()).called(1);
verify(() => mockDriveDao.removeAllDriveKeys()).called(1);
});

/// This is for the case when has user is true but the user is not logged in
Expand All @@ -605,12 +610,15 @@ void main() {
.thenAnswer((invocation) async {});
when(() => mockUserRepository.deleteUser())
.thenAnswer((invocation) async {});
when(() => mockDriveDao.removeAllDriveKeys())
.thenAnswer((invocation) async {});

await arDriveAuth.logout();

verifyNever(() => mockSecureKeyValueStore.remove('password'));
verifyNever(() => mockSecureKeyValueStore.remove('biometricEnabled'));
verify(() => mockDatabaseHelpers.deleteAllTables()).called(1);
verify(() => mockDriveDao.removeAllDriveKeys()).called(1);
verify(() => mockUserRepository.deleteUser()).called(1);
expect(() => arDriveAuth.currentUser,
throwsA(isA<AuthenticationUserIsNotLoggedInException>()));
Expand Down Expand Up @@ -674,6 +682,8 @@ void main() {
.thenAnswer((invocation) => Future.value(true));
when(() => mockDatabaseHelpers.deleteAllTables())
.thenAnswer((invocation) async {});
when(() => mockDriveDao.removeAllDriveKeys())
.thenAnswer((invocation) async {});

await arDriveAuth.login(wallet, 'password', ProfileType.json);

Expand All @@ -687,6 +697,7 @@ void main() {
verify(() => mockSecureKeyValueStore.remove('biometricEnabled'))
.called(1);
verify(() => mockDatabaseHelpers.deleteAllTables()).called(1);
verify(() => mockDriveDao.removeAllDriveKeys()).called(1);
verify(() => mockUserRepository.deleteUser()).called(1);
});
});
Expand Down Expand Up @@ -738,7 +749,8 @@ void main() {
when(() => mockUserRepository.saveUser(
'password', ProfileType.json, wallet))
.thenAnswer((invocation) => Future.value(null));

when(() => mockDriveDao.removeAllDriveKeys())
.thenAnswer((invocation) async {});
when(() => mockUserRepository.getUser('password'))
.thenAnswer((invocation) async => loggedUser);

Expand Down
Loading