Skip to content

Commit

Permalink
TW-1766: fix 500,404 error in POST request when login (#1946)
Browse files Browse the repository at this point in the history
* TW-1766: fix 500 error in POST request when login

* TW-1766: handle case 404 when call get recovery key
  • Loading branch information
sherlockvn authored Jul 17, 2024
1 parent 282c411 commit 9cc656a
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 63 deletions.
41 changes: 20 additions & 21 deletions lib/pages/bootstrap/bootstrap_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -333,25 +331,26 @@ class BootstrapDialogState extends State<BootstrapDialog> {
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(
Expand Down
104 changes: 62 additions & 42 deletions lib/pages/bootstrap/tom_bootstrap_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/encryption.dart';
import 'package:matrix/encryption/utils/bootstrap.dart';
import 'package:matrix/matrix.dart';

class TomBootstrapDialog extends StatefulWidget {
Expand Down Expand Up @@ -66,12 +65,10 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
@override
void initState() {
super.initState();
bootstrap =
widget.client.encryption!.bootstrap(onUpdate: (_) => setState(() {}));
_createBootstrap();
_initData();
}

void _createBootstrap() async {
void _initData() async {
WidgetsBinding.instance.addPostFrameCallback((_) async {
Matrix.of(context).showToMBootstrap.value = true;

Expand All @@ -80,7 +77,7 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
}

Future<void> setupAdditionalDioCacheOption(String userId) async {
Logs().d('TomBootstrapDialog::setupAdditionalDioCacheOption: $userId');
Logs().i('TomBootstrapDialog::setupAdditionalDioCacheOption: $userId');
DioCacheInterceptorForClient(userId).setup(getIt);
}

Expand All @@ -94,8 +91,11 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>

Future<void> _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!);
}
Expand All @@ -118,20 +118,21 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>

// 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',
);

Expand All @@ -145,10 +146,11 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
}
}
} 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;
Expand All @@ -160,6 +162,11 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
}
}

void _createBootstrap() {
bootstrap =
widget.client.encryption!.bootstrap(onUpdate: (_) => setState(() {}));
}

bool get isDataLoadingState =>
_uploadRecoveryKeyState == UploadRecoveryKeyState.dataLoading;

Expand All @@ -178,11 +185,11 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>

@override
Widget build(BuildContext context) {
Logs().d(
Logs().i(
'TomBootstrapDialogState::build(): BootstrapState = ${bootstrap?.state}',
);

Logs().d(
Logs().i(
'TomBootstrapDialogState::build(): RecoveryKeyState = $_uploadRecoveryKeyState',
);

Expand All @@ -206,12 +213,12 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
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}',
Expand All @@ -238,7 +245,7 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
});
break;
case UploadRecoveryKeyState.uploadError:
Logs().e('TomBootstrapDialogState::build(): upload recovery key error');
Logs().i('TomBootstrapDialogState::build(): upload recovery key error');
WidgetsBinding.instance.addPostFrameCallback((_) {
Matrix.of(context).showToMBootstrap.value = false;

Expand Down Expand Up @@ -273,6 +280,9 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
}

bool _existedRecoveryWordsInTom(String? key) {
Logs().i(
'TomBootstrapDialogState::_existedRecoveryWordsInTom(): $key, $_recoveryWords',
);
if (key == null && _recoveryWords != null) {
return true;
}
Expand All @@ -289,6 +299,9 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
_uploadRecoveryKeyState != UploadRecoveryKeyState.checkingRecoveryWork;

void _handleBootstrapState() {
Logs().i(
'TomBootstrapDialogState::_handleBootstrapState(): ${bootstrap?.state}',
);
if (bootstrap != null && _setUpSuccess) {
switch (bootstrap!.state) {
case BootstrapState.loading:
Expand Down Expand Up @@ -368,35 +381,35 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
}

Future<void> _wipeRecoveryWord() async {
await _deleteRecoveryWordsInteractor.execute().then(
(either) => either.fold(
(failure) {
Logs().e(
'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<void> _backUpInRecoveryVault(String? key) async {
if (key == null) {
setState(() {
Logs().d(
Logs().i(
'TomBootstrapDialogState::_backUpInRecoveryVault(): key null, upload failed',
);
_uploadRecoveryKeyState = UploadRecoveryKeyState.uploadError;
Expand All @@ -405,7 +418,7 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
await _saveRecoveryWordsInteractor.execute(key!).then(
(either) => either.fold(
(failure) {
Logs().d(
Logs().i(
'TomBootstrapDialogState::_backUpInRecoveryVault(): upload recoveryWords failed',
);
setState(
Expand All @@ -423,29 +436,36 @@ class TomBootstrapDialogState extends State<TomBootstrapDialog>
Future<void> _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(
'TomBootstrapDialogState::_unlockBackUp() Unable to unlock SSSS',
e,
s,
);
if (e is InvalidPassphraseException) {
Logs().i(
'TomBootstrapDialogState::_unlockBackUp(): InvalidPassphraseException: ${e.cause}',
);
}
setState(() {
_uploadRecoveryKeyState = UploadRecoveryKeyState.unlockError;
});
Expand Down

0 comments on commit 9cc656a

Please sign in to comment.