Skip to content

Commit

Permalink
feat(cat-voices): recover different keychain (#1147)
Browse files Browse the repository at this point in the history
  • Loading branch information
damian-molinski authored Nov 6, 2024
1 parent 997e524 commit ea17789
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:async';

import 'package:catalyst_voices/pages/registration/recover/bloc_recover_builder.dart';
import 'package:catalyst_voices/pages/registration/widgets/wallet_connection_status.dart';
import 'package:catalyst_voices/pages/registration/widgets/wallet_summary.dart';
Expand Down Expand Up @@ -33,31 +31,20 @@ class AccountDetailsPanel extends StatelessWidget {
style: theme.textTheme.titleMedium?.copyWith(color: textColor),
),
const SizedBox(height: 24),
Expanded(
const Expanded(
child: SingleChildScrollView(
child: _BlocAccountSummery(
onRetry: () => unawaited(_retryAccountRestore(context)),
),
child: _BlocAccountSummery(),
),
),
const SizedBox(height: 24),
const _BlocNavigation(),
],
);
}

Future<void> _retryAccountRestore(BuildContext context) async {
final recover = RegistrationCubit.of(context).recover;
await recover.recoverAccount();
}
}

class _BlocAccountSummery extends StatelessWidget {
final VoidCallback? onRetry;

const _BlocAccountSummery({
this.onRetry,
});
const _BlocAccountSummery();

@override
Widget build(BuildContext context) {
Expand All @@ -71,10 +58,7 @@ class _BlocAccountSummery extends StatelessWidget {
walletSummary: value.walletSummary,
),
Failure<AccountSummaryData, LocalizedException>(:final value) =>
_RecoverAccountFailure(
exception: value,
onRetry: onRetry,
),
_RecoverAccountFailure(exception: value),
_ => const Center(child: VoicesCircularProgressIndicator()),
};
},
Expand Down Expand Up @@ -117,18 +101,19 @@ class _RecoveredAccountSummary extends StatelessWidget {

class _RecoverAccountFailure extends StatelessWidget {
final LocalizedException exception;
final VoidCallback? onRetry;

const _RecoverAccountFailure({
required this.exception,
this.onRetry,
});

@override
Widget build(BuildContext context) {
return VoicesErrorIndicator(
message: exception.message(context),
onRetry: onRetry,
onRetry: () async {
final recover = RegistrationCubit.of(context).recover;
await recover.recoverAccount();
},
);
}
}
Expand Down Expand Up @@ -185,8 +170,12 @@ class _Navigation extends StatelessWidget {
),
const SizedBox(height: 10),
VoicesTextButton(
onTap: () => RegistrationCubit.of(context).previousStep(),
child: Text(context.l10n.back),
onTap: () async {
final cubit = RegistrationCubit.of(context);
await cubit.recover.reset();
cubit.previousStep();
},
child: Text(context.l10n.recoverDifferentKeychain),
),
],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ abstract interface class RecoverManager implements UnlockPasswordManager {
void setSeedPhraseWords(List<SeedPhraseWord> words);

Future<void> recoverAccount();

Future<void> reset();
}

final class RecoverCubit extends Cubit<RecoverStateData>
Expand All @@ -27,6 +29,7 @@ final class RecoverCubit extends Cubit<RecoverStateData>
final RegistrationService _registrationService;

SeedPhrase? _seedPhrase;
Account? _recoveredAccount;

RecoverCubit({
required UserService userService,
Expand Down Expand Up @@ -84,6 +87,8 @@ final class RecoverCubit extends Cubit<RecoverStateData>
lockFactor: lockFactor,
);

_recoveredAccount = account;

await _userService.useAccount(account);

final walletInfo = account.walletInfo;
Expand Down Expand Up @@ -119,6 +124,18 @@ final class RecoverCubit extends Cubit<RecoverStateData>
void onUnlockPasswordStateChanged(UnlockPasswordState data) {
emit(state.copyWith(unlockPasswordState: data));
}

@override
Future<void> reset() async {
final recoveredAccount = _recoveredAccount;
if (recoveredAccount != null) {
await _userService.removeKeychain(recoveredAccount.keychainId);
}

_recoveredAccount = null;

setSeedPhraseWords([]);
}
}

const _testWords = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ final class SessionCubit extends Cubit<SessionState>
}

Future<void> removeKeychain() {
return _userService.removeCurrentAccount();
return _userService.removeCurrentKeychain();
}

Future<void> switchToDummyAccount() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void main() {
// Given

// When
await userService.removeCurrentAccount();
await userService.removeCurrentKeychain();

// Then
expect(userService.keychain, isNull);
Expand All @@ -54,7 +54,7 @@ void main() {
// Given

// When
await userService.removeCurrentAccount();
await userService.removeCurrentKeychain();

// Gives time for stream to emit.
await Future<void>.delayed(const Duration(milliseconds: 100));
Expand All @@ -80,7 +80,7 @@ void main() {
// When
notifier.value = RegistrationProgress(keychainProgress: keychainProgress);

await userService.removeCurrentAccount();
await userService.removeCurrentKeychain();

// Gives time for stream to emit.
await Future<void>.delayed(const Duration(milliseconds: 100));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,12 @@ abstract class VoicesLocalizations {
/// **'With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. 

But it can be a bit tedious to enter every single time you want to use the app. 

In this next step, you\'ll set your Unlock Password for your current device. It\'s like a shortcut for proving ownership of your Keychain. 

Whenever you recover your account for the first time on a new device, you\'ll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.'**
String get recoveryUnlockPasswordInstructionsSubtitle;

/// No description provided for @recoverDifferentKeychain.
///
/// In en, this message translates to:
/// **'Restore a different keychain'**
String get recoverDifferentKeychain;

/// The header label in unlock dialog.
///
/// In en, this message translates to:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,9 @@ class VoicesLocalizationsEn extends VoicesLocalizations {
@override
String get recoveryUnlockPasswordInstructionsSubtitle => 'With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. 

But it can be a bit tedious to enter every single time you want to use the app. 

In this next step, you\'ll set your Unlock Password for your current device. It\'s like a shortcut for proving ownership of your Keychain. 

Whenever you recover your account for the first time on a new device, you\'ll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.';

@override
String get recoverDifferentKeychain => 'Restore a different keychain';

@override
String get unlockDialogHeader => 'Unlock Catalyst';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,9 @@ class VoicesLocalizationsEs extends VoicesLocalizations {
@override
String get recoveryUnlockPasswordInstructionsSubtitle => 'With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. 

But it can be a bit tedious to enter every single time you want to use the app. 

In this next step, you\'ll set your Unlock Password for your current device. It\'s like a shortcut for proving ownership of your Keychain. 

Whenever you recover your account for the first time on a new device, you\'ll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.';

@override
String get recoverDifferentKeychain => 'Restore a different keychain';

@override
String get unlockDialogHeader => 'Unlock Catalyst';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@
"recoveryAccountDetailsAction": "Set unlock password for this device",
"recoveryUnlockPasswordInstructionsTitle": "Set your Catalyst unlock password f\u2028or this device",
"recoveryUnlockPasswordInstructionsSubtitle": "With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. \u2028\u2028But it can be a bit tedious to enter every single time you want to use the app. \u2028\u2028In this next step, you'll set your Unlock Password for your current device. It's like a shortcut for proving ownership of your Keychain. \u2028\u2028Whenever you recover your account for the first time on a new device, you'll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.",
"recoverDifferentKeychain": "Restore a different keychain",
"unlockDialogHeader": "Unlock Catalyst",
"@unlockDialogHeader": {
"description": "The header label in unlock dialog."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ abstract interface class UserService {

Future<void> useKeychain(String id);

Future<void> removeCurrentAccount();
Future<void> removeCurrentKeychain();

Future<void> removeKeychain(String id);

Future<void> dispose();
}
Expand Down Expand Up @@ -110,16 +112,34 @@ final class UserServiceImpl implements UserService {
}

@override
Future<void> removeCurrentAccount() async {
Future<void> removeCurrentKeychain() async {
final keychain = _keychain;
if (keychain == null) {
_logger.warning('Called remove account but no active keychain found');
_logger.warning('Called remove keychain but no active found');
return;
}

await removeKeychain(keychain.id);
}

@override
Future<void> removeKeychain(String id) async {
if (!await _keychainProvider.exists(id)) {
_logger.warning(
'Called remove keychain[$id] but no such keychain was found',
);
return;
}

final isCurrentKeychain = id == _keychain?.id;

final keychain = await _keychainProvider.get(id);
await keychain.clear();
await _clearUser();
await _useKeychain(null);

if (isCurrentKeychain) {
await _clearUser();
await _useKeychain(null);
}
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void main() {

await service.useKeychain(keychainOne.id);
await service.useKeychain(keychainTwo.id);
await service.removeCurrentAccount();
await service.removeCurrentKeychain();

await service.dispose();
});
Expand Down Expand Up @@ -120,7 +120,7 @@ void main() {
// Then
expect(service.keychain, isNotNull);

await service.removeCurrentAccount();
await service.removeCurrentKeychain();

expect(service.keychain, isNull);
expect(await currentKeychain.isEmpty, isTrue);
Expand Down

0 comments on commit ea17789

Please sign in to comment.