diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 54f89437a..d26fd17a3 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -1,10 +1,12 @@ +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/encrypt.dart'; -import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; class AuthService with Store { @@ -14,6 +16,12 @@ class AuthService with Store { required this.settingsStore, }); + static const List _alwaysAuthenticateRoutes = [ + Routes.showKeys, + Routes.backup, + Routes.setupPin, + ]; + final FlutterSecureStorage secureStorage; final SharedPreferences sharedPreferences; final SettingsStore settingsStore; @@ -66,4 +74,33 @@ class AuthService with Store { return timeDifference.inMinutes; } + + Future authenticateAction(BuildContext context, + {Function(bool)? onAuthSuccess, String? route, Object? arguments}) async { + assert(route != null || onAuthSuccess != null, + 'Either route or onAuthSuccess param must be passed.'); + if (!requireAuth() && !_alwaysAuthenticateRoutes.contains(route)) { + if (onAuthSuccess != null) { + onAuthSuccess(true); + } else { + Navigator.of(context).pushNamed( + route ?? '', + arguments: arguments, + ); + } + return; + } + Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (!isAuthenticatedSuccessfully) { + onAuthSuccess?.call(false); + return; + } + if (onAuthSuccess != null) { + auth.close().then((value) => onAuthSuccess.call(true)); + } else { + auth.close(route: route, arguments: arguments); + } + }); + } } diff --git a/lib/di.dart b/lib/di.dart index 2d6e1ec34..584bc8b8e 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -499,7 +499,7 @@ Future setup( } getIt.registerFactory(() => - WalletListPage(walletListViewModel: getIt.get())); + WalletListPage(walletListViewModel: getIt.get(), authService: getIt.get(),)); getIt.registerFactory(() { final wallet = getIt.get().wallet!; @@ -593,7 +593,7 @@ Future setup( getIt.registerFactory(() => ConnectionSyncPage(getIt.get(), getIt.get())); - getIt.registerFactory(() => SecurityBackupPage(getIt.get())); + getIt.registerFactory(() => SecurityBackupPage(getIt.get(), getIt.get())); getIt.registerFactory(() => PrivacyPage(getIt.get())); @@ -926,7 +926,7 @@ Future setup( wallet: getIt.get().wallet!) ); - getIt.registerFactory(() => DesktopWalletSelectionDropDown(getIt.get())); + getIt.registerFactory(() => DesktopWalletSelectionDropDown(getIt.get(), getIt.get())); getIt.registerFactory(() => DesktopSidebarViewModel()); diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index 1ad831b1b..0bfcb359e 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -1,8 +1,9 @@ import 'package:another_flushbar/flushbar.dart'; +import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/desktop_dropdown_item.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/utils/show_bar.dart'; @@ -16,8 +17,10 @@ import 'package:flutter_mobx/flutter_mobx.dart'; class DesktopWalletSelectionDropDown extends StatefulWidget { final WalletListViewModel walletListViewModel; + final AuthService _authService; - DesktopWalletSelectionDropDown(this.walletListViewModel, {Key? key}) : super(key: key); + DesktopWalletSelectionDropDown(this.walletListViewModel, this._authService, {Key? key}) + : super(key: key); @override State createState() => _DesktopWalletSelectionDropDownState(); @@ -140,25 +143,12 @@ class _DesktopWalletSelectionDropDownState extends State _loadWallet(WalletListItem wallet) async { - if (await widget.walletListViewModel.checkIfAuthRequired()) { - await Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } + widget._authService.authenticateAction(context, + onAuthSuccess: (isAuthenticatedSuccessfully) async { + if (!isAuthenticatedSuccessfully) { + return; + } - try { - auth.changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); - await widget.walletListViewModel.loadWallet(wallet); - auth.hideProgressText(); - auth.close(); - setState(() {}); - } catch (e) { - auth.changeProcessText( - S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); - } - }); - } else { try { changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); await widget.walletListViewModel.loadWallet(wallet); @@ -167,7 +157,7 @@ class _DesktopWalletSelectionDropDownState extends State S.current.security_and_backup; @@ -27,35 +29,24 @@ class SecurityBackupPage extends BasePage { child: Column(mainAxisSize: MainAxisSize.min, children: [ SettingsCellWithArrow( title: S.current.show_keys, - handler: (_) => Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route: Routes.showKeys); - } - }), + handler: (_) => _authService.authenticateAction(context, route: Routes.showKeys), ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( title: S.current.create_backup, - handler: (_) => Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route: Routes.backup); - } - }), + handler: (_) => _authService.authenticateAction(context, route: Routes.backup), ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( - title: S.current.settings_change_pin, - handler: (_) => Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - auth.close( - route: isAuthenticatedSuccessfully ? Routes.setupPin : null, - arguments: (PinCodeState setupPinContext, String _) { - setupPinContext.close(); - }, - ); - })), + title: S.current.settings_change_pin, + handler: (_) => _authService.authenticateAction( + context, + route: Routes.setupPin, + arguments: (PinCodeState setupPinContext, String _) { + setupPinContext.close(); + }, + ), + ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer(builder: (_) { return SettingsSwitcherCell( @@ -63,8 +54,8 @@ class SecurityBackupPage extends BasePage { value: _securitySettingsViewModel.allowBiometricalAuthentication, onValueChange: (BuildContext context, bool value) { if (value) { - Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + _authService.authenticateAction(context, + onAuthSuccess: (isAuthenticatedSuccessfully) async { if (isAuthenticatedSuccessfully) { if (await _securitySettingsViewModel.biometricAuthenticated()) { _securitySettingsViewModel @@ -74,8 +65,6 @@ class SecurityBackupPage extends BasePage { _securitySettingsViewModel .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); } - - auth.close(); }); } else { _securitySettingsViewModel.setAllowBiometricalAuthentication(value); diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index a1e8c51b7..316203ddd 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,4 +1,4 @@ -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/show_bar.dart'; @@ -19,18 +19,21 @@ import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; class WalletListPage extends BasePage { - WalletListPage({required this.walletListViewModel}); + WalletListPage({required this.walletListViewModel, required this.authService}); final WalletListViewModel walletListViewModel; + final AuthService authService; @override - Widget body(BuildContext context) => WalletListBody(walletListViewModel: walletListViewModel); + Widget body(BuildContext context) => + WalletListBody(walletListViewModel: walletListViewModel, authService: authService); } class WalletListBody extends StatefulWidget { - WalletListBody({required this.walletListViewModel}); + WalletListBody({required this.walletListViewModel, required this.authService}); final WalletListViewModel walletListViewModel; + final AuthService authService; @override WalletListBodyState createState() => WalletListBodyState(); @@ -129,7 +132,8 @@ class WalletListBodyState extends State { fontSize: 22, fontWeight: FontWeight.w500, color: Theme.of(context) - .primaryTextTheme.headline6! + .primaryTextTheme + .headline6! .color!), ) ], @@ -201,61 +205,40 @@ class WalletListBodyState extends State { } Future _loadWallet(WalletListItem wallet) async { - if (await widget.walletListViewModel.checkIfAuthRequired()) { - await Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } + await widget.authService.authenticateAction(context, + onAuthSuccess: (isAuthenticatedSuccessfully) async { + if (!isAuthenticatedSuccessfully) { + return; + } - try { - auth.changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); - await widget.walletListViewModel.loadWallet(wallet); - auth.hideProgressText(); - auth.close(); - // only pop the wallets route in mobile as it will go back to dashboard page - // in desktop platforms the navigation tree is different - if (DeviceInfo.instance.isMobile) { - WidgetsBinding.instance.addPostFrameCallback((_) { - Navigator.of(context).pop(); - }); - } - } catch (e) { - auth.changeProcessText( - S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); - } - }); - } else { try { changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); await widget.walletListViewModel.loadWallet(wallet); - hideProgressText(); + await hideProgressText(); // only pop the wallets route in mobile as it will go back to dashboard page // in desktop platforms the navigation tree is different if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pop(); + WidgetsBinding.instance.addPostFrameCallback((_) { + Navigator.of(context).pop(); + }); } } catch (e) { changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); } - } + }); } Future _removeWallet(WalletListItem wallet) async { - if (widget.walletListViewModel.checkIfAuthRequired()) { - await Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } - _onSuccessfulAuth(wallet, auth); - }); - } else { - _onSuccessfulAuth(wallet, null); - } + widget.authService.authenticateAction(context, + onAuthSuccess: (isAuthenticatedSuccessfully) async { + if (!isAuthenticatedSuccessfully) { + return; + } + _onSuccessfulAuth(wallet); + }); } - void _onSuccessfulAuth(WalletListItem wallet, AuthPageState? auth) async { + void _onSuccessfulAuth(WalletListItem wallet) async { bool confirmed = false; await showPopUp( context: context, @@ -275,31 +258,23 @@ class WalletListBodyState extends State { if (confirmed) { try { - auth != null - ? auth.changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name)) - : changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name)); + changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name)); await widget.walletListViewModel.remove(wallet); hideProgressText(); } catch (e) { - auth != null - ? auth.changeProcessText( - S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), - ) - : changeProcessText( - S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), - ); + changeProcessText( + S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), + ); } } - - auth?.close(); } void changeProcessText(String text) { _progressBar = createBar(text, duration: null)..show(context); } - void hideProgressText() { - Future.delayed(Duration(milliseconds: 50), () { + Future hideProgressText() async { + await Future.delayed(Duration(milliseconds: 50), () { _progressBar?.dismiss(); _progressBar = null; });