mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-29 21:55:58 +00:00
WIP: desktop password
This commit is contained in:
parent
21f18326d8
commit
4dd8ae23c5
5 changed files with 174 additions and 15 deletions
|
@ -30,7 +30,8 @@ import 'package:stackwallet/pages/loading_view.dart';
|
|||
import 'package:stackwallet/pages/pinpad_views/create_pin_view.dart';
|
||||
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
|
||||
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_login_view.dart';
|
||||
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
|
||||
import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
|
||||
import 'package:stackwallet/providers/global/base_currencies_provider.dart';
|
||||
// import 'package:stackwallet/providers/global/has_authenticated_start_state_provider.dart';
|
||||
|
@ -207,6 +208,7 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
|||
late final Completer<void> loadingCompleter;
|
||||
|
||||
bool didLoad = false;
|
||||
bool _desktopHasPassword = false;
|
||||
|
||||
Future<void> load() async {
|
||||
try {
|
||||
|
@ -218,6 +220,11 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
|||
await DB.instance.init();
|
||||
await _prefs.init();
|
||||
|
||||
if (Util.isDesktop) {
|
||||
_desktopHasPassword =
|
||||
await ref.read(storageCryptoHandlerProvider).hasPassword();
|
||||
}
|
||||
|
||||
_notificationsService = ref.read(notificationsProvider);
|
||||
_nodeService = ref.read(nodeServiceChangeNotifierProvider);
|
||||
_tradesService = ref.read(tradesServiceProvider);
|
||||
|
@ -545,21 +552,23 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
|||
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
// FlutterNativeSplash.remove();
|
||||
if (_wallets.hasWallets || _prefs.hasPin) {
|
||||
// return HomeView();
|
||||
|
||||
if (Util.isDesktop &&
|
||||
(_wallets.hasWallets || _desktopHasPassword)) {
|
||||
String? startupWalletId;
|
||||
if (ref.read(prefsChangeNotifierProvider).gotoWalletOnStartup) {
|
||||
startupWalletId =
|
||||
ref.read(prefsChangeNotifierProvider).startupWalletId;
|
||||
}
|
||||
|
||||
// TODO proper desktop auth view
|
||||
if (Util.isDesktop) {
|
||||
Future<void>.delayed(Duration.zero).then((value) =>
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
DesktopHomeView.routeName, (route) => false));
|
||||
return Container();
|
||||
return DesktopLoginView(startupWalletId: startupWalletId);
|
||||
} else if (!Util.isDesktop &&
|
||||
(_wallets.hasWallets || _prefs.hasPin)) {
|
||||
// return HomeView();
|
||||
|
||||
String? startupWalletId;
|
||||
if (ref.read(prefsChangeNotifierProvider).gotoWalletOnStartup) {
|
||||
startupWalletId =
|
||||
ref.read(prefsChangeNotifierProvider).startupWalletId;
|
||||
}
|
||||
|
||||
return LockscreenView(
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
|
||||
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
|
||||
|
@ -18,7 +20,7 @@ import 'package:stackwallet/widgets/progress_bar.dart';
|
|||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:zxcvbn/zxcvbn.dart';
|
||||
|
||||
class CreatePasswordView extends StatefulWidget {
|
||||
class CreatePasswordView extends ConsumerStatefulWidget {
|
||||
const CreatePasswordView({
|
||||
Key? key,
|
||||
this.secureStore = const SecureStorageWrapper(
|
||||
|
@ -31,10 +33,10 @@ class CreatePasswordView extends StatefulWidget {
|
|||
final FlutterSecureStorageInterface secureStore;
|
||||
|
||||
@override
|
||||
State<CreatePasswordView> createState() => _CreatePasswordViewState();
|
||||
ConsumerState<CreatePasswordView> createState() => _CreatePasswordViewState();
|
||||
}
|
||||
|
||||
class _CreatePasswordViewState extends State<CreatePasswordView> {
|
||||
class _CreatePasswordViewState extends ConsumerState<CreatePasswordView> {
|
||||
late final TextEditingController passwordController;
|
||||
late final TextEditingController passwordRepeatController;
|
||||
|
||||
|
@ -76,8 +78,16 @@ class _CreatePasswordViewState extends State<CreatePasswordView> {
|
|||
return;
|
||||
}
|
||||
|
||||
await widget.secureStore
|
||||
.write(key: "stackDesktopPassword", value: passphrase);
|
||||
try {
|
||||
await ref.read(storageCryptoHandlerProvider).initFromNew(passphrase);
|
||||
} catch (e) {
|
||||
unawaited(showFloatingFlushBar(
|
||||
type: FlushBarType.warning,
|
||||
message: "Error: $e",
|
||||
context: context,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
unawaited(Navigator.of(context)
|
||||
|
|
47
lib/pages_desktop_specific/desktop_login_view.dart
Normal file
47
lib/pages_desktop_specific/desktop_login_view.dart
Normal file
|
@ -0,0 +1,47 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
|
||||
class DesktopLoginView extends StatefulWidget {
|
||||
const DesktopLoginView({
|
||||
Key? key,
|
||||
this.startupWalletId,
|
||||
}) : super(key: key);
|
||||
|
||||
static const String routeName = "/desktopLogin";
|
||||
|
||||
final String? startupWalletId;
|
||||
|
||||
@override
|
||||
State<DesktopLoginView> createState() => _DesktopLoginViewState();
|
||||
}
|
||||
|
||||
class _DesktopLoginViewState extends State<DesktopLoginView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Login",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
PrimaryButton(
|
||||
label: "Login",
|
||||
onPressed: () {
|
||||
// todo auth
|
||||
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
DesktopHomeView.routeName,
|
||||
(route) => false,
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/utilities/desktop_password_service.dart';
|
||||
|
||||
final storageCryptoHandlerProvider = Provider<DPS>((ref) => DPS());
|
89
lib/utilities/desktop_password_service.dart
Normal file
89
lib/utilities/desktop_password_service.dart
Normal file
|
@ -0,0 +1,89 @@
|
|||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:stack_wallet_backup/secure_storage.dart';
|
||||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
||||
const String _kKeyBlobKey = "swbKeyBlobKeyStringID";
|
||||
|
||||
String _getMessageFromException(Object exception) {
|
||||
if (exception is IncorrectPassphrase) {
|
||||
return exception.errMsg();
|
||||
}
|
||||
if (exception is BadDecryption) {
|
||||
return exception.errMsg();
|
||||
}
|
||||
if (exception is InvalidLength) {
|
||||
return exception.errMsg();
|
||||
}
|
||||
if (exception is EncodingError) {
|
||||
return exception.errMsg();
|
||||
}
|
||||
|
||||
return exception.toString();
|
||||
}
|
||||
|
||||
class DPS {
|
||||
StorageCryptoHandler? _handler;
|
||||
final SecureStorageWrapper secureStorageWrapper;
|
||||
|
||||
StorageCryptoHandler get handler {
|
||||
if (_handler == null) {
|
||||
throw Exception(
|
||||
"DPS: attempted to access handler without proper authentication");
|
||||
}
|
||||
return _handler!;
|
||||
}
|
||||
|
||||
DPS({
|
||||
this.secureStorageWrapper = const SecureStorageWrapper(
|
||||
FlutterSecureStorage(),
|
||||
),
|
||||
});
|
||||
|
||||
Future<void> initFromNew(String passphrase) async {
|
||||
if (_handler != null) {
|
||||
throw Exception("DPS: attempted to re initialize with new passphrase");
|
||||
}
|
||||
|
||||
try {
|
||||
_handler = await StorageCryptoHandler.fromNewPassphrase(passphrase);
|
||||
await secureStorageWrapper.write(
|
||||
key: _kKeyBlobKey,
|
||||
value: await _handler!.getKeyBlob(),
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"${_getMessageFromException(e)}\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initFromExisting(String passphrase) async {
|
||||
if (_handler != null) {
|
||||
throw Exception(
|
||||
"DPS: attempted to re initialize with existing passphrase");
|
||||
}
|
||||
final keyBlob = await secureStorageWrapper.read(key: _kKeyBlobKey);
|
||||
|
||||
if (keyBlob == null) {
|
||||
throw Exception(
|
||||
"DPS: failed to find keyBlob while attempting to initialize with existing passphrase");
|
||||
}
|
||||
|
||||
try {
|
||||
_handler = await StorageCryptoHandler.fromExisting(passphrase, keyBlob);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"${_getMessageFromException(e)}\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> hasPassword() async {
|
||||
return (await secureStorageWrapper.read(key: _kKeyBlobKey)) != null;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue