Change Password: Confirm before signing out from other devices (#374)
This commit is contained in:
parent
cf6b4f5423
commit
17f5a7996a
3 changed files with 55 additions and 20 deletions
|
@ -398,5 +398,9 @@
|
|||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters."
|
||||
},
|
||||
"noInternetConnection": "No internet connection",
|
||||
"pleaseCheckYourInternetConnectionAndTryAgain": "Please check your internet connection and try again."
|
||||
"pleaseCheckYourInternetConnectionAndTryAgain": "Please check your internet connection and try again.",
|
||||
"signOutFromOtherDevices": "Sign out from other devices",
|
||||
"signOutOtherBody": "If you think someone might know your password, you can force all other devices using your account to sign out.",
|
||||
"signOutOtherDevices": "Sign out other devices",
|
||||
"doNotSignOut": "Do not sign out"
|
||||
}
|
||||
|
|
|
@ -441,6 +441,7 @@ class UserService {
|
|||
Future<void> registerOrUpdateSrp(
|
||||
Uint8List loginKey, {
|
||||
SetKeysRequest? setKeysRequest,
|
||||
bool logOutOtherDevices = false,
|
||||
}) async {
|
||||
try {
|
||||
final String username = const Uuid().v4().toString();
|
||||
|
@ -496,6 +497,7 @@ class UserService {
|
|||
'setupID': setupSRPResponse.setupID,
|
||||
'srpM1': base64Encode(SRP6Util.encodeBigInt(clientM!)),
|
||||
'updatedKeyAttr': setKeysRequest.toMap(),
|
||||
'logOutOtherDevices': logOutOtherDevices,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -608,8 +610,9 @@ class UserService {
|
|||
|
||||
Future<void> updateKeyAttributes(
|
||||
KeyAttributes keyAttributes,
|
||||
Uint8List loginKey,
|
||||
) async {
|
||||
Uint8List loginKey, {
|
||||
required bool logoutOtherDevices,
|
||||
}) async {
|
||||
try {
|
||||
final setKeyRequest = SetKeysRequest(
|
||||
kekSalt: keyAttributes.kekSalt,
|
||||
|
@ -618,11 +621,11 @@ class UserService {
|
|||
memLimit: keyAttributes.memLimit,
|
||||
opsLimit: keyAttributes.opsLimit,
|
||||
);
|
||||
await registerOrUpdateSrp(loginKey, setKeysRequest: setKeyRequest);
|
||||
// await _enteDio.put(
|
||||
// "/users/keys",
|
||||
// data: setKeyRequest.toMap(),
|
||||
// );
|
||||
await registerOrUpdateSrp(
|
||||
loginKey,
|
||||
setKeysRequest: setKeyRequest,
|
||||
logOutOtherDevices: logoutOtherDevices,
|
||||
);
|
||||
await _config.setKeyAttributes(keyAttributes);
|
||||
} catch (e) {
|
||||
_logger.severe(e);
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:ente_auth/services/user_service.dart';
|
|||
import 'package:ente_auth/ui/account/recovery_key_page.dart';
|
||||
import 'package:ente_auth/ui/common/dynamic_fab.dart';
|
||||
import 'package:ente_auth/ui/common/web_page.dart';
|
||||
import 'package:ente_auth/ui/components/models/button_type.dart';
|
||||
import 'package:ente_auth/ui/home_page.dart';
|
||||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:ente_auth/utils/navigation_util.dart';
|
||||
|
@ -24,8 +25,7 @@ enum PasswordEntryMode {
|
|||
class PasswordEntryPage extends StatefulWidget {
|
||||
final PasswordEntryMode mode;
|
||||
|
||||
const PasswordEntryPage({required this.mode, Key? key})
|
||||
: super(key: key);
|
||||
const PasswordEntryPage({required this.mode, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PasswordEntryPage> createState() => _PasswordEntryPageState();
|
||||
|
@ -180,10 +180,11 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
.copyWith(fontSize: 14),
|
||||
tags: {
|
||||
'underline': StyledTextTag(
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
|
@ -356,10 +357,11 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: context.l10n.howItWorks,
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -374,13 +376,18 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
}
|
||||
|
||||
void _updatePassword() async {
|
||||
final logOutFromOthers = await logOutFromOtherDevices(context);
|
||||
final dialog =
|
||||
createProgressDialog(context, context.l10n.generatingEncryptionKeys);
|
||||
await dialog.show();
|
||||
try {
|
||||
final result = await Configuration.instance
|
||||
.getAttributesForNewPassword(_passwordController1.text);
|
||||
await UserService.instance.updateKeyAttributes(result.item1, result.item2);
|
||||
await UserService.instance.updateKeyAttributes(
|
||||
result.item1,
|
||||
result.item2,
|
||||
logoutOtherDevices: logOutFromOthers,
|
||||
);
|
||||
await dialog.hide();
|
||||
showShortToast(context, context.l10n.passwordChangedSuccessfully);
|
||||
Navigator.of(context).pop();
|
||||
|
@ -394,13 +401,34 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<bool> logOutFromOtherDevices(BuildContext context) async {
|
||||
bool logOutFromOther = true;
|
||||
await showChoiceDialog(
|
||||
context,
|
||||
title: context.l10n.signOutFromOtherDevices,
|
||||
body: context.l10n.signOutOtherBody,
|
||||
isDismissible: false,
|
||||
firstButtonLabel: context.l10n.signOutOtherDevices,
|
||||
firstButtonType: ButtonType.critical,
|
||||
firstButtonOnTap: () async {
|
||||
logOutFromOther = true;
|
||||
},
|
||||
secondButtonLabel: context.l10n.doNotSignOut,
|
||||
secondButtonOnTap: () async {
|
||||
logOutFromOther = false;
|
||||
},
|
||||
);
|
||||
return logOutFromOther;
|
||||
}
|
||||
|
||||
Future<void> _showRecoveryCodeDialog(String password) async {
|
||||
final l10n = context.l10n;
|
||||
final dialog =
|
||||
createProgressDialog(context, l10n.generatingEncryptionKeysTitle);
|
||||
await dialog.show();
|
||||
try {
|
||||
final KeyGenResult result = await Configuration.instance.generateKey(password);
|
||||
final KeyGenResult result =
|
||||
await Configuration.instance.generateKey(password);
|
||||
Configuration.instance.setVolatilePassword(null);
|
||||
await dialog.hide();
|
||||
onDone() async {
|
||||
|
|
Loading…
Reference in a new issue