bio auth on mac + package updates for 3.19.3/5 (#1398)

* bio auth mac fix

* remove comment and change duration from 2 to 0

* cherry pick previous changes

* workaround for secure storage bug on mac

* bump version to 3.19.5 (because breez will need this version anyways)

* some code cleanup

* some changess didn't get saved

* just documenting the issue [skip ci]

* undo accidental removal + minor code cleanup

* merge conflicts

* Minor UI change [skip ci]

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
Matthew Fosse 2024-05-06 12:55:05 -07:00 committed by GitHub
parent 3f3cd10158
commit e5be737236
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 730 additions and 555 deletions

View file

@ -42,7 +42,7 @@ jobs:
- name: Flutter action - name: Flutter action
uses: subosito/flutter-action@v1 uses: subosito/flutter-action@v1
with: with:
flutter-version: "3.10.x" flutter-version: "3.19.5"
channel: stable channel: stable
- name: Install package dependencies - name: Install package dependencies

View file

@ -43,11 +43,14 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
build_resolvers: ^2.0.9 build_resolvers: ^2.0.9
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
dependency_overrides:
watcher: ^1.1.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -39,10 +39,13 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
dependency_overrides:
watcher: ^1.1.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -28,11 +28,13 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
build_resolvers: ^2.0.9 build_resolvers: ^2.0.9
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^2.0.1 hive_generator: ^2.0.1
dependency_overrides:
watcher: ^1.1.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -24,11 +24,13 @@ dependency_overrides:
git: git:
url: https://github.com/cake-tech/web3dart.git url: https://github.com/cake-tech/web3dart.git
ref: cake ref: cake
watcher: ^1.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
flutter: flutter:
# assets: # assets:
# - images/a_dot_burr.jpeg # - images/a_dot_burr.jpeg

View file

@ -36,11 +36,12 @@ dependency_overrides:
git: git:
url: https://github.com/cake-tech/ledger-flutter.git url: https://github.com/cake-tech/ledger-flutter.git
ref: cake ref: cake
watcher: ^1.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0

View file

@ -24,11 +24,14 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
build_resolvers: ^2.0.9 build_resolvers: ^2.0.9
hive_generator: ^1.1.3 hive_generator: ^1.1.3
dependency_overrides:
watcher: ^1.1.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -26,11 +26,14 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
build_resolvers: ^2.0.9 build_resolvers: ^2.0.9
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
dependency_overrides:
watcher: ^1.1.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -32,10 +32,13 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11 build_runner: ^2.4.7
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
dependency_overrides:
watcher: ^1.1.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -28,12 +28,14 @@ dependency_overrides:
git: git:
url: https://github.com/cake-tech/web3dart.git url: https://github.com/cake-tech/web3dart.git
ref: cake ref: cake
watcher: ^1.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
build_runner: ^2.1.11 build_runner: ^2.4.7
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View file

@ -26,10 +26,13 @@ dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
build_runner: ^2.1.11 build_runner: ^2.4.7
mobx_codegen: ^2.0.7 mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
dependency_overrides:
watcher: ^1.1.0
flutter: flutter:
# assets: # assets:
# - images/a_dot_burr.jpeg # - images/a_dot_burr.jpeg

View file

@ -42,12 +42,7 @@ class AuthService with Store {
Future<void> setPassword(String password) async { Future<void> setPassword(String password) async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPassword = encodedPinCode(pin: password); final encodedPassword = encodedPinCode(pin: password);
// secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless await writeSecureStorage(secureStorage, key: key, value: encodedPassword);
// we delete what's there first:
if (Platform.isMacOS) {
await secureStorage.delete(key: key);
}
await secureStorage.write(key: key, value: encodedPassword);
} }
Future<bool> canAuthenticate() async { Future<bool> canAuthenticate() async {
@ -74,7 +69,11 @@ class AuthService with Store {
void saveLastAuthTime() { void saveLastAuthTime() {
int timestamp = DateTime.now().millisecondsSinceEpoch; int timestamp = DateTime.now().millisecondsSinceEpoch;
secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString()); writeSecureStorage(
secureStorage,
key: SecureKey.lastAuthTimeMilliseconds,
value: timestamp.toString(),
);
} }
Future<bool> requireAuth() async { Future<bool> requireAuth() async {

View file

@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/themes/theme_list.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
@ -275,7 +276,7 @@ class BackupService {
if (currentTransactionPriorityKeyLegacy != null) if (currentTransactionPriorityKeyLegacy != null)
await _sharedPreferences.setInt( await _sharedPreferences.setInt(
PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy);
if (currentBitcoinElectrumSererId != null) if (currentBitcoinElectrumSererId != null)
await _sharedPreferences.setInt( await _sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId); PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId);
@ -373,16 +374,15 @@ class BackupService {
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = keychainJSON[backupPasswordKey] as String; final backupPassword = keychainJSON[backupPasswordKey] as String;
await _flutterSecureStorage.delete(key: backupPasswordKey); await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword);
await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
keychainWalletsInfo.forEach((dynamic rawInfo) async { keychainWalletsInfo.forEach((dynamic rawInfo) async {
final info = rawInfo as Map<String, dynamic>; final info = rawInfo as Map<String, dynamic>;
await importWalletKeychainInfo(info); await importWalletKeychainInfo(info);
}); });
await _flutterSecureStorage.delete(key: pinCodeKey); await writeSecureStorage(_flutterSecureStorage,
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
keychainDumpFile.deleteSync(); keychainDumpFile.deleteSync();
} }
@ -401,16 +401,15 @@ class BackupService {
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = keychainJSON[backupPasswordKey] as String; final backupPassword = keychainJSON[backupPasswordKey] as String;
await _flutterSecureStorage.delete(key: backupPasswordKey); await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword);
await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
keychainWalletsInfo.forEach((dynamic rawInfo) async { keychainWalletsInfo.forEach((dynamic rawInfo) async {
final info = rawInfo as Map<String, dynamic>; final info = rawInfo as Map<String, dynamic>;
await importWalletKeychainInfo(info); await importWalletKeychainInfo(info);
}); });
await _flutterSecureStorage.delete(key: pinCodeKey); await writeSecureStorage(_flutterSecureStorage,
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
keychainDumpFile.deleteSync(); keychainDumpFile.deleteSync();
} }

View file

@ -20,8 +20,7 @@ class KeyService {
key: SecretStoreKey.moneroWalletPassword, walletName: walletName); key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
final encodedPassword = encodeWalletPassword(password: password); final encodedPassword = encodeWalletPassword(password: password);
await _secureStorage.delete(key: key); await writeSecureStorage(_secureStorage, key: key, value: encodedPassword);
await _secureStorage.write(key: key, value: encodedPassword);
} }
Future<void> deleteWalletPassword({required String walletName}) async { Future<void> deleteWalletPassword({required String walletName}) async {

View file

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
// For now, we can create a utility function to handle this. // For now, we can create a utility function to handle this.
// //
@ -25,3 +26,13 @@ Future<String?> readSecureStorage(FlutterSecureStorage secureStorage, String key
return result; return result;
} }
Future<void> writeSecureStorage(FlutterSecureStorage secureStorage,
{required String key, required String value}) async {
// delete the value before writing on macOS because of a weird bug
// https://github.com/mogol/flutter_secure_storage/issues/581
if (Platform.isMacOS) {
await secureStorage.delete(key: key);
}
await secureStorage.write(key: key, value: value);
}

View file

@ -1,32 +1,29 @@
import 'package:local_auth/local_auth.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_local_authentication/flutter_local_authentication.dart';
class BiometricAuth { class BiometricAuth {
final _localAuth = LocalAuthentication(); final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication();
Future<bool> isAuthenticated() async { Future<bool> isAuthenticated() async {
try { try {
return await _localAuth.authenticate( final authenticated = await _flutterLocalAuthenticationPlugin.authenticate();
localizedReason: S.current.biometric_auth_reason, return authenticated;
options: AuthenticationOptions( } catch (e) {
biometricOnly: true,
useErrorDialogs: true,
stickyAuth: false));
} on PlatformException catch (e) {
print(e); print(e);
} }
return false; return false;
} }
Future<bool> canCheckBiometrics() async { Future<bool> canCheckBiometrics() async {
bool canAuthenticate;
try { try {
return await _localAuth.canCheckBiometrics; canAuthenticate = await _flutterLocalAuthenticationPlugin.canAuthenticate();
} on PlatformException catch (e) { await _flutterLocalAuthenticationPlugin.setTouchIDAuthenticationAllowableReuseDuration(0);
print(e); } catch (error) {
print("Exception checking support. $error");
canAuthenticate = false;
} }
return false; return canAuthenticate;
} }
} }

View file

@ -1,5 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'dart:convert'; import 'dart:convert';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -147,8 +148,8 @@ Future<void> ios_migrate_pin() async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPassword = encodedPinCode(pin: pinPassword); final encodedPassword = encodedPinCode(pin: pinPassword);
await flutterSecureStorage.delete(key: key); await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword);
await flutterSecureStorage.write(key: key, value: encodedPassword);
await prefs.setBool('ios_migration_pin_completed', true); await prefs.setBool('ios_migration_pin_completed', true);
} }

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/cake_hive.dart';
@ -10,8 +11,7 @@ Future<List<int>> getEncryptionKey(
key = CakeHive.generateSecureKey(); key = CakeHive.generateSecureKey();
final keyStringified = key.join(','); final keyStringified = key.join(',');
String storageKey = 'transactionDescriptionsBoxKey'; String storageKey = 'transactionDescriptionsBoxKey';
await secureStorage.delete(key: storageKey); await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified);
await secureStorage.write(key: storageKey, value: keyStringified);
} else { } else {
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
} }

View file

@ -751,6 +751,50 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations {
@override @override
String get scrimOnTapHintRaw => "Scrip on Tap"; String get scrimOnTapHintRaw => "Scrip on Tap";
@override
// TODO: implement collapsedHint
String get collapsedHint => "collapsedHint";
@override
// TODO: implement expandedHint
String get expandedHint => "expandedHint";
@override
// TODO: implement expansionTileCollapsedHint
String get expansionTileCollapsedHint => "expansionTileCollapsedHint";
@override
// TODO: implement expansionTileCollapsedTapHint
String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint";
@override
// TODO: implement expansionTileExpandedHint
String get expansionTileExpandedHint => "expansionTileExpandedHint";
@override
// TODO: implement expansionTileExpandedTapHint
String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint";
@override
// TODO: implement scanTextButtonLabel
String get scanTextButtonLabel => "scanTextButtonLabel";
@override
// TODO: implement lookUpButtonLabel
String get lookUpButtonLabel => "lookUpButtonLabel";
@override
// TODO: implement menuDismissLabel
String get menuDismissLabel => "menuDismissLabel";
@override
// TODO: implement searchWebButtonLabel
String get searchWebButtonLabel => "searchWebButtonLabel";
@override
// TODO: implement shareButtonLabel
String get shareButtonLabel => "shareButtonLabel";
} }
/// Cupertino Support /// Cupertino Support
@ -955,4 +999,24 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations {
@override @override
String get noSpellCheckReplacementsLabel => ""; String get noSpellCheckReplacementsLabel => "";
@override
// TODO: implement clearButtonLabel
String get clearButtonLabel => "clearButtonLabel";
@override
// TODO: implement lookUpButtonLabel
String get lookUpButtonLabel => "lookUpButtonLabel";
@override
// TODO: implement menuDismissLabel
String get menuDismissLabel => "menuDismissLabel";
@override
// TODO: implement searchWebButtonLabel
String get searchWebButtonLabel => "searchWebButtonLabel";
@override
// TODO: implement shareButtonLabel
String get shareButtonLabel => "shareButtonLabel";
} }

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,6 @@ final _settingsNavigatorKey = GlobalKey<NavigatorState>();
class DesktopSettingsPage extends StatefulWidget { class DesktopSettingsPage extends StatefulWidget {
const DesktopSettingsPage({super.key}); const DesktopSettingsPage({super.key});
@override @override
State<DesktopSettingsPage> createState() => _DesktopSettingsPageState(); State<DesktopSettingsPage> createState() => _DesktopSettingsPageState();
} }
@ -33,22 +32,21 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
return Scaffold( return Scaffold(
body: Container( body: Container(
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
child: Column( child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding(
padding: const EdgeInsets.fromLTRB(24, 24, 24, 4),
child: Text(
S.current.settings,
style: textXLarge(),
),
),
Expanded( Expanded(
child: Row( flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding(
padding: const EdgeInsets.fromLTRB(24, 24, 24, 4),
child: Text(
S.current.settings,
style: textXLarge(),
),
),
Expanded( Expanded(
flex: 1,
child: ListView.separated( child: ListView.separated(
padding: EdgeInsets.only(top: 0), padding: EdgeInsets.only(top: 0),
itemBuilder: (_, index) { itemBuilder: (_, index) {
@ -78,27 +76,27 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
itemCount: itemCount, itemCount: itemCount,
), ),
), ),
Flexible(
flex: 2,
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: Navigator(
key: _settingsNavigatorKey,
initialRoute: Routes.empty_no_route,
onGenerateRoute: (settings) => Router.createRoute(settings),
onGenerateInitialRoutes:
(NavigatorState navigator, String initialRouteName) {
return [
navigator
.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
];
},
),
),
)
], ],
), ),
), ),
Flexible(
flex: 2,
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: Navigator(
key: _settingsNavigatorKey,
initialRoute: Routes.empty_no_route,
onGenerateRoute: (settings) => Router.createRoute(settings),
onGenerateInitialRoutes:
(NavigatorState navigator, String initialRouteName) {
return [
navigator
.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
];
},
),
),
)
], ],
), ),
), ),

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
@ -58,7 +60,7 @@ class SecurityBackupPage extends BasePage {
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
), ),
), ),
if (DeviceInfo.instance.isMobile) if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux)
Observer(builder: (_) { Observer(builder: (_) {
return SettingsSwitcherCell( return SettingsSwitcherCell(
title: S.current.settings_allow_biometrical_authentication, title: S.current.settings_allow_biometrical_authentication,

View file

@ -146,7 +146,7 @@ class ConnectScreen extends StatelessWidget {
ElevatedButton( ElevatedButton(
onPressed: connect, onPressed: connect,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
primary: Colors.blue, // primary: Colors.blue,
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30), borderRadius: BorderRadius.circular(30),
@ -211,7 +211,7 @@ class DisconnectScreen extends StatelessWidget {
ElevatedButton( ElevatedButton(
onPressed: disconnect, onPressed: disconnect,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
primary: Colors.red, // primary: Colors.red,
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30), borderRadius: BorderRadius.circular(30),

View file

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
@ -58,7 +59,6 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
} }
Future<void> storeCookie(String value) async { Future<void> storeCookie(String value) async {
await widget.secureStorage.delete(key: COOKIE_KEY); await writeSecureStorage(widget.secureStorage, key: COOKIE_KEY, value: value);
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
} }
} }

View file

@ -1,8 +1,14 @@
import 'package:cake_wallet/core/seed_validator.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Annotation extends Comparable<Annotation> {
extension Compare<T> on Comparable<T> {
bool operator <=(T other) => compareTo(other) <= 0;
bool operator >=(T other) => compareTo(other) >= 0;
bool operator <(T other) => compareTo(other) < 0;
bool operator >(T other) => compareTo(other) > 0;
}
class Annotation implements Comparable<Annotation> {
Annotation({required this.range, required this.style}); Annotation({required this.range, required this.style});
final TextRange range; final TextRange range;
@ -12,7 +18,7 @@ class Annotation extends Comparable<Annotation> {
int compareTo(Annotation other) => range.start.compareTo(other.range.start); int compareTo(Annotation other) => range.start.compareTo(other.range.start);
} }
class TextAnnotation extends Comparable<TextAnnotation> { class TextAnnotation implements Comparable<TextAnnotation> {
TextAnnotation({required this.text, required this.style}); TextAnnotation({required this.text, required this.style});
final TextStyle style; final TextStyle style;

View file

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/provider_types.dart';
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
@ -434,79 +435,83 @@ abstract class SettingsStoreBase with Store {
// secure storage keys: // secure storage keys:
reaction( reaction(
(_) => allowBiometricalAuthentication, (_) => allowBiometricalAuthentication,
(bool biometricalAuthentication) => secureStorage.write( (bool biometricalAuthentication) => writeSecureStorage(secureStorage,
key: SecureKey.allowBiometricalAuthenticationKey, key: SecureKey.allowBiometricalAuthenticationKey,
value: biometricalAuthentication.toString())); value: biometricalAuthentication.toString()));
reaction( reaction(
(_) => selectedCake2FAPreset, (_) => selectedCake2FAPreset,
(Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write( (Cake2FAPresetsOptions selectedCake2FAPreset) => writeSecureStorage(secureStorage,
key: SecureKey.selectedCake2FAPreset, key: SecureKey.selectedCake2FAPreset,
value: selectedCake2FAPreset.serialize().toString())); value: selectedCake2FAPreset.serialize().toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForAccessingWallet, (_) => shouldRequireTOTP2FAForAccessingWallet,
(bool requireTOTP2FAForAccessingWallet) => secureStorage.write( (bool requireTOTP2FAForAccessingWallet) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, key: SecureKey.shouldRequireTOTP2FAForAccessingWallet,
value: requireTOTP2FAForAccessingWallet.toString())); value: requireTOTP2FAForAccessingWallet.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForSendsToContact, (_) => shouldRequireTOTP2FAForSendsToContact,
(bool requireTOTP2FAForSendsToContact) => secureStorage.write( (bool requireTOTP2FAForSendsToContact) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForSendsToContact, key: SecureKey.shouldRequireTOTP2FAForSendsToContact,
value: requireTOTP2FAForSendsToContact.toString())); value: requireTOTP2FAForSendsToContact.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForSendsToNonContact, (_) => shouldRequireTOTP2FAForSendsToNonContact,
(bool requireTOTP2FAForSendsToNonContact) => secureStorage.write( (bool requireTOTP2FAForSendsToNonContact) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact,
value: requireTOTP2FAForSendsToNonContact.toString())); value: requireTOTP2FAForSendsToNonContact.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForSendsToInternalWallets, (_) => shouldRequireTOTP2FAForSendsToInternalWallets,
(bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write( (bool requireTOTP2FAForSendsToInternalWallets) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets,
value: requireTOTP2FAForSendsToInternalWallets.toString())); value: requireTOTP2FAForSendsToInternalWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForExchangesToInternalWallets, (_) => shouldRequireTOTP2FAForExchangesToInternalWallets,
(bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write( (bool requireTOTP2FAForExchangesToInternalWallets) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets,
value: requireTOTP2FAForExchangesToInternalWallets.toString())); value: requireTOTP2FAForExchangesToInternalWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForExchangesToExternalWallets, (_) => shouldRequireTOTP2FAForExchangesToExternalWallets,
(bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write( (bool requireTOTP2FAForExchangesToExternalWallets) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets,
value: requireTOTP2FAForExchangesToExternalWallets.toString())); value: requireTOTP2FAForExchangesToExternalWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForAddingContacts, (_) => shouldRequireTOTP2FAForAddingContacts,
(bool requireTOTP2FAForAddingContacts) => secureStorage.write( (bool requireTOTP2FAForAddingContacts) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForAddingContacts, key: SecureKey.shouldRequireTOTP2FAForAddingContacts,
value: requireTOTP2FAForAddingContacts.toString())); value: requireTOTP2FAForAddingContacts.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForCreatingNewWallets, (_) => shouldRequireTOTP2FAForCreatingNewWallets,
(bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write( (bool requireTOTP2FAForCreatingNewWallets) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets,
value: requireTOTP2FAForCreatingNewWallets.toString())); value: requireTOTP2FAForCreatingNewWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings, (_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
(bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write( (bool requireTOTP2FAForAllSecurityAndBackupSettings) => writeSecureStorage(secureStorage,
key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
value: requireTOTP2FAForAllSecurityAndBackupSettings.toString())); value: requireTOTP2FAForAllSecurityAndBackupSettings.toString()));
reaction((_) => useTOTP2FA, reaction(
(bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString())); (_) => useTOTP2FA,
(bool use) =>
writeSecureStorage(secureStorage, key: SecureKey.useTOTP2FA, value: use.toString()));
reaction((_) => totpSecretKey, reaction(
(String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey)); (_) => totpSecretKey,
(String totpKey) =>
writeSecureStorage(secureStorage, key: SecureKey.totpSecretKey, value: totpKey));
reaction( reaction(
(_) => pinTimeOutDuration, (_) => pinTimeOutDuration,
(PinCodeRequiredDuration pinCodeInterval) => secureStorage.write( (PinCodeRequiredDuration pinCodeInterval) => writeSecureStorage(secureStorage,
key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString())); key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString()));
reaction( reaction(

View file

@ -106,14 +106,10 @@ abstract class AuthViewModelBase with Store {
@action @action
Future<void> biometricAuth() async { Future<void> biometricAuth() async {
try { try {
final canBiometricAuth = await _biometricAuth.canCheckBiometrics(); if (await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated()) {
state = ExecutedSuccessfullyState();
if (canBiometricAuth) { } else {
final isAuthenticated = await _biometricAuth.isAuthenticated(); throw Exception('Biometric authentication failed');
if (isAuthenticated) {
state = ExecutedSuccessfullyState();
}
} }
} catch (e) { } catch (e) {
state = FailureState(e.toString()); state = FailureState(e.toString());

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
@ -37,8 +38,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
@action @action
Future<void> save() async { Future<void> save() async {
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
await secureStorage.delete(key: key); await writeSecureStorage(secureStorage, key: key, value: backupPassword);
await secureStorage.write(key: key, value: backupPassword);
secretStore.write(key: key, value: backupPassword); secretStore.write(key: key, value: backupPassword);
} }
} }

View file

@ -10,6 +10,7 @@ import cw_monero
import device_info_plus import device_info_plus
import devicelocale import devicelocale
import flutter_inappwebview_macos import flutter_inappwebview_macos
import flutter_local_authentication
import flutter_secure_storage_macos import flutter_secure_storage_macos
import in_app_review import in_app_review
import package_info import package_info
@ -26,6 +27,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))

View file

@ -26,6 +26,8 @@ PODS:
- flutter_inappwebview_macos (0.0.1): - flutter_inappwebview_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- OrderedSet (~> 5.0) - OrderedSet (~> 5.0)
- flutter_local_authentication (1.2.0):
- FlutterMacOS
- flutter_secure_storage_macos (6.1.1): - flutter_secure_storage_macos (6.1.1):
- FlutterMacOS - FlutterMacOS
- FlutterMacOS (1.0.0) - FlutterMacOS (1.0.0)
@ -56,6 +58,7 @@ DEPENDENCIES:
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`) - flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
- flutter_local_authentication (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
@ -83,6 +86,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos :path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos
flutter_inappwebview_macos: flutter_inappwebview_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos
flutter_local_authentication:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos
flutter_secure_storage_macos: flutter_secure_storage_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
FlutterMacOS: FlutterMacOS:
@ -110,6 +115,7 @@ SPEC CHECKSUMS:
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
flutter_local_authentication: 85674893931e1c9cfa7c9e4f5973cb8c56b018b0
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0

View file

@ -26,15 +26,17 @@ dependencies:
path_provider: ^2.0.11 path_provider: ^2.0.11
mobx: ^2.1.4 mobx: ^2.1.4
flutter_mobx: ^2.0.6+5 flutter_mobx: ^2.0.6+5
flutter_slidable: ^2.0.0 flutter_slidable: ^3.0.1
share_plus: ^4.0.10 share_plus: ^4.0.10
# date_range_picker: ^1.0.6 # date_range_picker: ^1.0.6
#https://api.flutter.dev/flutter/material/showDateRangePicker.html #https://api.flutter.dev/flutter/material/showDateRangePicker.html
dio: ^4.0.6 dio: ^4.0.6
hive: ^2.2.3 hive: ^2.2.3
hive_flutter: ^1.1.0 hive_flutter: ^1.1.0
local_auth: ^2.1.0
local_auth_android: 1.0.21 local_auth_android: 1.0.21
flutter_local_authentication:
git:
url: https://github.com/cake-tech/flutter_local_authentication
package_info: ^2.0.0 package_info: ^2.0.0
#package_info_plus: ^1.4.2 #package_info_plus: ^1.4.2
devicelocale: devicelocale:

View file

@ -4,4 +4,4 @@ version: 0.0.0
publish_to: none publish_to: none
environment: environment:
sdk: ">=2.17.5 <3.0.0" sdk: ">=3.1.0 <4.0.0"