From 8323b47d28b231d85e947f591b13a74a6a15bebe Mon Sep 17 00:00:00 2001 From: --global Date: Thu, 11 Jul 2024 15:56:46 +0700 Subject: [PATCH 1/2] TW-1766: fix 500 error in POST request when login --- lib/pages/bootstrap/tom_bootstrap_dialog.dart | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/lib/pages/bootstrap/tom_bootstrap_dialog.dart b/lib/pages/bootstrap/tom_bootstrap_dialog.dart index a2f4e5707d..896093ca7d 100644 --- a/lib/pages/bootstrap/tom_bootstrap_dialog.dart +++ b/lib/pages/bootstrap/tom_bootstrap_dialog.dart @@ -14,7 +14,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:linagora_design_flutter/colors/linagora_sys_colors.dart'; import 'package:lottie/lottie.dart'; import 'package:matrix/encryption.dart'; -import 'package:matrix/encryption/utils/bootstrap.dart'; import 'package:matrix/matrix.dart'; class TomBootstrapDialog extends StatefulWidget { @@ -57,19 +56,17 @@ class TomBootstrapDialogState extends State @override void initState() { super.initState(); - bootstrap = - widget.client.encryption!.bootstrap(onUpdate: (_) => setState(() {})); - _createBootstrap(); + _initData(); } - void _createBootstrap() async { + void _initData() async { WidgetsBinding.instance.addPostFrameCallback((_) async { await _loadingData(); }); } Future setupAdditionalDioCacheOption(String userId) async { - Logs().d('TomBootstrapDialog::setupAdditionalDioCacheOption: $userId'); + Logs().i('TomBootstrapDialog::setupAdditionalDioCacheOption: $userId'); DioCacheInterceptorForClient(userId).setup(getIt); } @@ -83,8 +80,11 @@ class TomBootstrapDialogState extends State Future _loadingData() async { _uploadRecoveryKeyState = UploadRecoveryKeyState.dataLoading; + Logs().i('_loadingData: $_uploadRecoveryKeyState'); await widget.client.roomsLoading; await widget.client.accountDataLoading; + + Logs().i('_loadingData: roomDataLoaded & accountDataLoaded'); if (widget.client.userID != null) { await setupAdditionalDioCacheOption(widget.client.userID!); } @@ -107,30 +107,32 @@ class TomBootstrapDialogState extends State // Display first login bootstrap if enabled if (widget.client.encryption?.keyManager.enabled == true) { - Logs().d( + Logs().i( 'TomBootstrapDialog::_initializeRecoveryKeyState: Showing bootstrap dialog when encryption is enabled', ); if (await widget.client.encryption?.keyManager.isCached() == false || await widget.client.encryption?.crossSigning.isCached() == false || widget.client.isUnknownSession && mounted) { final recoveryWords = await _getRecoveryWords(); + _createBootstrap(); if (recoveryWords != null) { _recoveryWords = recoveryWords; _uploadRecoveryKeyState = UploadRecoveryKeyState.useExisting; setState(() {}); return; } else { - Logs().d( + Logs().i( 'TomBootstrapDialog::_initializeRecoveryKeyState(): no recovery existed then call bootstrap', ); Navigator.of(context, rootNavigator: false).pop(false); } } } else { - Logs().d( + Logs().i( 'TomBootstrapDialog::_initializeRecoveryKeyState(): encryption is not enabled', ); final recoveryWords = await _getRecoveryWords(); + _createBootstrap(); _wipe = recoveryWords != null; if (recoveryWords != null) { _uploadRecoveryKeyState = UploadRecoveryKeyState.wipeRecovery; @@ -142,6 +144,11 @@ class TomBootstrapDialogState extends State } } + void _createBootstrap() { + bootstrap = + widget.client.encryption!.bootstrap(onUpdate: (_) => setState(() {})); + } + bool get isDataLoadingState => _uploadRecoveryKeyState == UploadRecoveryKeyState.dataLoading; @@ -160,11 +167,11 @@ class TomBootstrapDialogState extends State @override Widget build(BuildContext context) { - Logs().d( + Logs().i( 'TomBootstrapDialogState::build(): BootstrapState = ${bootstrap?.state}', ); - Logs().d( + Logs().i( 'TomBootstrapDialogState::build(): RecoveryKeyState = $_uploadRecoveryKeyState', ); @@ -186,12 +193,12 @@ class TomBootstrapDialogState extends State break; case UploadRecoveryKeyState.created: if (_createNewRecoveryKeySuccess()) { - Logs().d( + Logs().i( 'TomBootstrapDialogState::build(): start backup process with key ${bootstrap?.newSsssKey!.recoveryKey}', ); final key = bootstrap?.newSsssKey!.recoveryKey; WidgetsBinding.instance.addPostFrameCallback((_) { - Logs().d( + Logs().i( 'TomBootstrapDialogState::build(): check if key is already in TOM = ${_existedRecoveryWordsInTom( key, )} - ${_recoveryWords?.words}', @@ -216,7 +223,7 @@ class TomBootstrapDialogState extends State }); break; case UploadRecoveryKeyState.uploadError: - Logs().e('TomBootstrapDialogState::build(): upload recovery key error'); + Logs().i('TomBootstrapDialogState::build(): upload recovery key error'); WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context, rootNavigator: false).pop(); }); @@ -269,6 +276,9 @@ class TomBootstrapDialogState extends State } bool _existedRecoveryWordsInTom(String? key) { + Logs().i( + 'TomBootstrapDialogState::_existedRecoveryWordsInTom(): $key, $_recoveryWords', + ); if (key == null && _recoveryWords != null) { return true; } @@ -285,6 +295,9 @@ class TomBootstrapDialogState extends State _uploadRecoveryKeyState != UploadRecoveryKeyState.checkingRecoveryWork; void _handleBootstrapState() { + Logs().i( + 'TomBootstrapDialogState::_handleBootstrapState(): ${bootstrap?.state}', + ); if (bootstrap != null && _setUpSuccess) { switch (bootstrap!.state) { case BootstrapState.loading: @@ -367,7 +380,7 @@ class TomBootstrapDialogState extends State await _deleteRecoveryWordsInteractor.execute().then( (either) => either.fold( (failure) { - Logs().e( + Logs().i( 'TomBootstrapDialogState::_wipeRecoveryWord(): wipe recoveryWords failed', ); if (Matrix.of(context).twakeSupported) { @@ -392,7 +405,7 @@ class TomBootstrapDialogState extends State Future _backUpInRecoveryVault(String? key) async { if (key == null) { setState(() { - Logs().d( + Logs().i( 'TomBootstrapDialogState::_backUpInRecoveryVault(): key null, upload failed', ); _uploadRecoveryKeyState = UploadRecoveryKeyState.uploadError; @@ -401,7 +414,7 @@ class TomBootstrapDialogState extends State await _saveRecoveryWordsInteractor.execute(key!).then( (either) => either.fold( (failure) { - Logs().d( + Logs().i( 'TomBootstrapDialogState::_backUpInRecoveryVault(): upload recoveryWords failed', ); setState( @@ -419,22 +432,24 @@ class TomBootstrapDialogState extends State Future _unlockBackUp() async { final recoveryWords = _recoveryWords; if (recoveryWords == null) { - Logs().e('TomBootstrapDialogState::_unlockBackUp(): recoveryWords null'); + Logs().i('TomBootstrapDialogState::_unlockBackUp(): recoveryWords null'); setState(() { _uploadRecoveryKeyState = UploadRecoveryKeyState.unlockError; }); return; } try { - Logs().d('TomBootstrapDialogState::_unlockBackUp() unlocking'); + Logs().i( + 'TomBootstrapDialogState::_unlockBackUp() unlocking: ${recoveryWords.words}', + ); await bootstrap?.newSsssKey!.unlock( keyOrPassphrase: recoveryWords.words, ); - Logs().d('TomBootstrapDialogState::_unlockBackUp() self Signing'); + Logs().i('TomBootstrapDialogState::_unlockBackUp() self Signing'); await bootstrap?.client.encryption!.crossSigning.selfSign( keyOrPassphrase: recoveryWords.words, ); - Logs().d('TomBootstrapDialogState::_unlockBackUp() open existing SSSS'); + Logs().i('TomBootstrapDialogState::_unlockBackUp() open existing SSSS'); await bootstrap?.openExistingSsss(); } catch (e, s) { Logs().w( @@ -442,6 +457,11 @@ class TomBootstrapDialogState extends State e, s, ); + if (e is InvalidPassphraseException) { + Logs().i( + 'TomBootstrapDialogState::_unlockBackUp(): InvalidPassphraseException: ${e.cause}', + ); + } setState(() { _uploadRecoveryKeyState = UploadRecoveryKeyState.unlockError; }); From 304439aeb095099631d20dd5a598d0c73eacd9fd Mon Sep 17 00:00:00 2001 From: --global Date: Mon, 15 Jul 2024 08:28:57 +0700 Subject: [PATCH 2/2] TW-1766: handle case 404 when call get recovery key --- lib/pages/bootstrap/bootstrap_dialog.dart | 41 +++++++++-------- lib/pages/bootstrap/tom_bootstrap_dialog.dart | 44 +++++++++---------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/lib/pages/bootstrap/bootstrap_dialog.dart b/lib/pages/bootstrap/bootstrap_dialog.dart index 0a786d86de..073c9983c8 100644 --- a/lib/pages/bootstrap/bootstrap_dialog.dart +++ b/lib/pages/bootstrap/bootstrap_dialog.dart @@ -15,8 +15,6 @@ import 'package:matrix/encryption/utils/bootstrap.dart'; import 'package:matrix/matrix.dart'; import 'package:share_plus/share_plus.dart'; -import '../key_verification/key_verification_dialog.dart'; - class BootstrapDialog extends StatefulWidget { final bool wipe; final Client client; @@ -333,25 +331,26 @@ class BootstrapDialogState extends State { const Expanded(child: Divider()), ], ), - const SizedBox(height: 16), - ElevatedButton.icon( - icon: const Icon(Icons.cast_connected_outlined), - label: Text(L10n.of(context)!.transferFromAnotherDevice), - onPressed: _recoveryKeyInputLoading - ? null - : () async { - final req = await TwakeDialog - .showFutureLoadingDialogFullScreen( - future: () => widget.client - .userDeviceKeys[widget.client.userID!]! - .startVerification(), - ); - if (req.error != null) return; - await KeyVerificationDialog(request: req.result!) - .show(context); - Navigator.of(context, rootNavigator: false).pop(); - }, - ), + // TODO: TW-1766: temporary disable right now, because not supported yet + // const SizedBox(height: 16), + // ElevatedButton.icon( + // icon: const Icon(Icons.cast_connected_outlined), + // label: Text(L10n.of(context)!.transferFromAnotherDevice), + // onPressed: _recoveryKeyInputLoading + // ? null + // : () async { + // final req = await TwakeDialog + // .showFutureLoadingDialogFullScreen( + // future: () => widget.client + // .userDeviceKeys[widget.client.userID!]! + // .startVerification(), + // ); + // if (req.error != null) return; + // await KeyVerificationDialog(request: req.result!) + // .show(context); + // Navigator.of(context, rootNavigator: false).pop(); + // }, + // ), const SizedBox(height: 16), ElevatedButton.icon( style: ElevatedButton.styleFrom( diff --git a/lib/pages/bootstrap/tom_bootstrap_dialog.dart b/lib/pages/bootstrap/tom_bootstrap_dialog.dart index 896093ca7d..74835c27a7 100644 --- a/lib/pages/bootstrap/tom_bootstrap_dialog.dart +++ b/lib/pages/bootstrap/tom_bootstrap_dialog.dart @@ -377,29 +377,29 @@ class TomBootstrapDialogState extends State } Future _wipeRecoveryWord() async { - await _deleteRecoveryWordsInteractor.execute().then( - (either) => either.fold( - (failure) { - Logs().i( - 'TomBootstrapDialogState::_wipeRecoveryWord(): wipe recoveryWords failed', - ); - if (Matrix.of(context).twakeSupported) { - setState( - () => _uploadRecoveryKeyState = - UploadRecoveryKeyState.wipeRecoveryFailed, - ); - } else { - setState( - () => - _uploadRecoveryKeyState = UploadRecoveryKeyState.initial, - ); - } - }, - (success) => setState( + await _deleteRecoveryWordsInteractor.execute().then((either) { + _createBootstrap(); + either.fold( + (failure) { + Logs().i( + 'TomBootstrapDialogState::_wipeRecoveryWord(): wipe recoveryWords failed', + ); + if (Matrix.of(context).twakeSupported) { + setState( + () => _uploadRecoveryKeyState = + UploadRecoveryKeyState.wipeRecoveryFailed, + ); + } else { + setState( () => _uploadRecoveryKeyState = UploadRecoveryKeyState.initial, - ), - ), - ); + ); + } + }, + (success) => setState(() { + _uploadRecoveryKeyState = UploadRecoveryKeyState.initial; + }), + ); + }); } Future _backUpInRecoveryVault(String? key) async {