Skip to content

Commit bb346af

Browse files
committed
wip
1 parent 162499e commit bb346af

File tree

3 files changed

+96
-92
lines changed

3 files changed

+96
-92
lines changed

lib/cubit/account_cubit.dart

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -378,16 +378,6 @@ class AccountCubit extends Cubit<AccountState> {
378378
l.w('Unable to changeEmailAddress due to a transport error. Cannot be sure if the request was successful or not. Details: $e');
379379
emit(AccountEmailChangeRequested(currentUser,
380380
'Due to a network failure, we cannot say whether your request succeeded or not. We have left you signed in using your old email address but if the operation did eventually succeed, you may find that you are signed out soon. Please check your new email address for a verification request. It might take a moment to arrive but if it does, that suggests the process did work so just verify your new address, sign out of the app and then sign-in using the new email address. If unsure if it worked, sign in with your previous email address next time and try again when you have a more stable network connection.'));
381-
382-
//} on KeeMaybeOfflineException {
383-
//TODO: confirm if can get a KeeMaybeOfflineException here
384-
// l.i('Unable to authenticate since initial identification failed, probably due to a transport error. App should continue to work offline if user has previously stored their Vault.');
385-
// final prefs = await SharedPreferences.getInstance();
386-
// await prefs.setString('user.current.email', user.email!);
387-
// if (user.id?.isNotEmpty ?? false) {
388-
// await prefs.setString('user.authMaterialUserIdMap.${user.emailHashed}', user.id!);
389-
// }
390-
// emit(AccountAuthenticationBypassed(user));
391381
}
392382
return false;
393383
}
@@ -407,26 +397,26 @@ class AccountCubit extends Cubit<AccountState> {
407397
await prefs.setString('user.authMaterialUserIdMap.${user.emailHashed}', user.id!);
408398
}
409399
final newUser = await User.fromEmail(newEmailAddress);
410-
//TODO: what is the below on about? maybe that we need to make sure that the vault is locked when we do this operation, thus ensuring that leaving the user signed in due to network faults, manipulation, etc. doesn't leave them with access to their vault data. but what about taking exports? shouldn't that be allowed? probably yes, as long as they are currently verified and can thus log in normally. then cliking the button to change email address will lock the vault and kick them to the screen that ultimately sends their request to this function.
411-
//TODO: verify that we can only get here if Vault is already locked. Throw exception earlier if we can detect that state?
412400
emit(AccountChosen(newUser));
401+
await signout();
402+
// await AppConfig.router.navigateTo(AppConfig.navigatorKey.currentContext!, Routes.root, clearStack: true);
413403
//await BlocProvider.of<AccountCubit>(context).forgetUser(vc.signout);
414404
return true;
415405
} on KeeLoginFailedMITMException {
416406
rethrow;
417407
} on KeeLoginRequiredException {
418408
l.w('Unable to changeEmailAddress due to a 403.');
419409
emit(AccountEmailChangeRequested(user,
420-
'Due to an authentication problem, we were unable to change your email address. Probably it has been too long since you last signed in with your previous email address. We have left you signed in using your old email address but you may find that you are signed out soon. Please sign out and then sign in again with your previous email address and try again when you have enough time to complete the operation within 10 minutes.'));
410+
'Due to an authentication problem, we were unable to change your email address. Probably it has been too long since you last signed in with your previous email address. Please click Cancel and then sign in again with your previous email address and try this email change again when you have enough time to complete the operation within 10 minutes.'));
421411
} on FormatException {
422412
// Local validation
423413
l.i('Unable to changeEmailAddress due to FormatException.');
424-
emit(AccountEmailChangeRequested(user, 'Please enter the correct password for your existing Kee Vault account.'));
414+
emit(AccountEmailChangeRequested(user, 'Please enter the correct password for your Kee Vault account.'));
425415
} on KeeInvalidRequestException {
426416
// Local validation should mean this is unlikely to happen outside of malicious acts
427417
l.i('Unable to changeEmailAddress due to 400 response.');
428418
emit(AccountEmailChangeRequested(user,
429-
'Please double check that you have entered the correct password for your existing Kee Vault account. Also check that you have entered a valid email address of no more than 70 characters.'));
419+
'Please double check that you have entered the correct password for your Kee Vault account. Also check that you have entered a valid email address of no more than 70 characters.'));
430420
} on KeeServerConflictException {
431421
l.i('Unable to changeEmailAddress due to 409 response.');
432422
emit(AccountEmailChangeRequested(user,
@@ -437,17 +427,7 @@ class AccountCubit extends Cubit<AccountState> {
437427
} on KeeServiceTransportException catch (e) {
438428
l.w('Unable to changeEmailAddress due to a transport error. Cannot be sure if the request was successful or not. Details: $e');
439429
emit(AccountEmailChangeRequested(user,
440-
'Due to a network failure, we cannot say whether your request succeeded or not. We have left you signed in using your old email address but if the operation did eventually succeed, you may find that you are signed out soon. Please check your new email address for a verification request. It might take a moment to arrive but if it does, that suggests the process did work so just verify your new address, sign out of the app and then sign-in using the new email address. If unsure if it worked, sign in with your previous email address next time and try again when you have a more stable network connection.'));
441-
442-
//} on KeeMaybeOfflineException {
443-
//TODO: confirm if can get a KeeMaybeOfflineException here
444-
// l.i('Unable to authenticate since initial identification failed, probably due to a transport error. App should continue to work offline if user has previously stored their Vault.');
445-
// final prefs = await SharedPreferences.getInstance();
446-
// await prefs.setString('user.current.email', user.email!);
447-
// if (user.id?.isNotEmpty ?? false) {
448-
// await prefs.setString('user.authMaterialUserIdMap.${user.emailHashed}', user.id!);
449-
// }
450-
// emit(AccountAuthenticationBypassed(user));
430+
'Due to a network failure, we cannot say whether your request succeeded or not. Please check your new email address for a verification request. It might take a moment to arrive but if it does, that suggests the process did work so just verify your new address, click Cancel below and then sign-in using the new email address. If unsure if it worked, sign in with your previous email address next time and try again when you have a more stable network connection.'));
451431
}
452432
return false;
453433
}

lib/widgets/account_email_change.dart

Lines changed: 85 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
66
import 'package:keevault/cubit/account_cubit.dart';
77
import '../config/app.dart';
88
import '../config/routes.dart';
9+
import '../cubit/vault_cubit.dart';
910
import '../generated/l10n.dart';
11+
import '../logging/logger.dart';
1012

1113
typedef SubmitCallback = Future<void> Function(String string);
1214

@@ -21,13 +23,20 @@ class AccountEmailChangeWidget extends StatefulWidget {
2123

2224
class _AccountEmailChangeWidgetState extends State<AccountEmailChangeWidget> {
2325
Future<void> cancel() async {
24-
// We always sign the user out. Might be nice to send them back to their Vault if that's where they came from (i.e. they have a validated and active account) but might be hard to do securely so will ignore that edge case initially.
26+
// We always sign the user out. Might be nice to send them back to their Vault if that's
27+
// where they came from (i.e. they have a validated and active account) but might be
28+
// hard to do securely so will ignore that edge case initially.
2529
final accountCubit = BlocProvider.of<AccountCubit>(context);
2630
await accountCubit.signout();
2731
await AppConfig.router.navigateTo(AppConfig.navigatorKey.currentContext!, Routes.root, clearStack: true);
2832
}
2933

3034
Future<bool> changeEmailAddress(String password, String newEmailAddress) async {
35+
final vaultCubit = BlocProvider.of<VaultCubit>(context);
36+
if (vaultCubit.state is! VaultInitial) {
37+
l.e('Vault is not in expected state so we will not proceed with the email address change. Found state: ${vaultCubit.state.runtimeType}');
38+
return false;
39+
}
3140
setState(() {
3241
changing = true;
3342
});
@@ -157,7 +166,7 @@ class _AccountEmailChangeWidgetState extends State<AccountEmailChangeWidget> {
157166
},
158167
),
159168
Padding(
160-
padding: const EdgeInsets.fromLTRB(0, 12, 0, 32),
169+
padding: const EdgeInsets.fromLTRB(0, 12, 0, 16),
161170
child: TextFormField(
162171
enabled: !disableChange,
163172
controller: _newEmailAddress,
@@ -181,7 +190,7 @@ class _AccountEmailChangeWidgetState extends State<AccountEmailChangeWidget> {
181190
),
182191
),
183192
Padding(
184-
padding: const EdgeInsets.fromLTRB(0, 12, 0, 32),
193+
padding: const EdgeInsets.fromLTRB(0, 12, 0, 16),
185194
child: TextFormField(
186195
enabled: !disableChange,
187196
controller: _currentPassword,
@@ -214,66 +223,81 @@ class _AccountEmailChangeWidgetState extends State<AccountEmailChangeWidget> {
214223
keyboardType: TextInputType.visiblePassword,
215224
),
216225
),
217-
FilledButton(
218-
onPressed: changing || disableChange
219-
? null
220-
: () async {
221-
// final navigator = Navigator.of(context);
222-
final sm = ScaffoldMessenger.of(context);
223-
setState(() {
224-
showPreviousError = false;
225-
});
226-
if (_formKey.currentState!.validate()) {
227-
_formKey.currentState!.save();
228-
try {
229-
final result =
230-
await changeEmailAddress(submittedValuePassword!, submittedValueNewEmailAddress!);
231-
if (result) {
232-
sm.showSnackBar(SnackBar(
233-
content: Text(str.emailChanged),
234-
duration: Duration(seconds: 6),
235-
));
236-
await AppConfig.router
237-
.navigateTo(AppConfig.navigatorKey.currentContext!, Routes.root, clearStack: true);
238-
}
239-
} finally {
240-
if (mounted) {
241-
setState(() {
242-
changing = false;
243-
});
226+
227+
if (state.error != null)
228+
Padding(
229+
padding: const EdgeInsets.only(bottom: 16.0),
230+
child: Text(
231+
state.error!,
232+
textAlign: TextAlign.left,
233+
style: theme.textTheme.titleMedium?.copyWith(color: theme.colorScheme.error),
234+
),
235+
),
236+
237+
ButtonBar(
238+
alignment: MainAxisAlignment.end,
239+
children: [
240+
OutlinedButton(
241+
onPressed: changing
242+
? null
243+
: () async {
244+
await cancel();
245+
},
246+
child: changing
247+
? Container(
248+
width: 24,
249+
height: 24,
250+
padding: const EdgeInsets.all(2.0),
251+
child: const CircularProgressIndicator(
252+
strokeWidth: 3,
253+
),
254+
)
255+
: Text(str.alertCancel),
256+
),
257+
ElevatedButton(
258+
onPressed: changing || disableChange
259+
? null
260+
: () async {
261+
// final navigator = Navigator.of(context);
262+
final sm = ScaffoldMessenger.of(context);
263+
setState(() {
264+
showPreviousError = false;
265+
});
266+
if (_formKey.currentState!.validate()) {
267+
_formKey.currentState!.save();
268+
try {
269+
final result =
270+
await changeEmailAddress(submittedValuePassword!, submittedValueNewEmailAddress!);
271+
if (result) {
272+
sm.showSnackBar(SnackBar(
273+
content: Text(str.emailChanged),
274+
duration: Duration(seconds: 6),
275+
));
276+
await AppConfig.router.navigateTo(AppConfig.navigatorKey.currentContext!, Routes.root,
277+
clearStack: true);
278+
}
279+
} finally {
280+
if (mounted) {
281+
setState(() {
282+
changing = false;
283+
});
284+
}
285+
}
244286
}
245-
}
246-
}
247-
},
248-
child: changing
249-
? Container(
250-
width: 24,
251-
height: 24,
252-
padding: const EdgeInsets.all(2.0),
253-
child: const CircularProgressIndicator(
254-
strokeWidth: 3,
255-
),
256-
)
257-
: Text(str.changeEmail),
258-
),
259-
OutlinedButton(
260-
onPressed: changing
261-
? null
262-
: () async {
263-
await cancel();
264-
},
265-
child: changing
266-
? Container(
267-
width: 24,
268-
height: 24,
269-
padding: const EdgeInsets.all(2.0),
270-
child: const CircularProgressIndicator(
271-
strokeWidth: 3,
272-
),
273-
)
274-
: Text(str.alertCancel),
287+
},
288+
child: changing
289+
? Container(
290+
width: 24,
291+
height: 24,
292+
padding: const EdgeInsets.all(2.0),
293+
child: const CircularProgressIndicator(
294+
strokeWidth: 3,
295+
),
296+
)
297+
: Text(str.changeEmail),
298+
),
299+
],
275300
),
276-
//TODO: Cancel button location
277301
//TODO: Handle back press - cancel automatically.
278302
]),
279303
),

lib/widgets/account_wrapper.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ class AccountWrapperState extends State<AccountWrapperWidget> {
133133
}
134134
return Text(str.vaultStatusUnknownState);
135135
}, listenWhen: (prev, current) {
136-
if (current is AccountAuthenticated) {
137-
if (prev is! AccountEmailNotVerified && prev is! AccountExpired) {
138-
return false;
139-
}
136+
if (current is AccountAuthenticated && prev is! AccountEmailNotVerified && prev is! AccountExpired) {
137+
// &&
138+
//prev is! AccountEmailChangeRequested) {
139+
return false;
140140
}
141141
return true;
142142
}, listener: (context, state) async {
@@ -148,7 +148,7 @@ class AccountWrapperState extends State<AccountWrapperWidget> {
148148
Routes.createAccount.replaceFirst(':email', state.user.email ?? ''),
149149
transition: TransitionType.inFromRight,
150150
);
151-
} else if (state is AccountAuthenticated) {
151+
} else if (state is AccountAuthenticated && state is! AccountEmailChangeRequested) {
152152
final vaultCubit = BlocProvider.of<VaultCubit>(context);
153153
await vaultCubit.startup(state.user, null);
154154
}

0 commit comments

Comments
 (0)