Change Password: Confirm before signing out from other devices (#1542)
This commit is contained in:
commit
6763a42fc6
7
lib/generated/intl/messages_en.dart
generated
7
lib/generated/intl/messages_en.dart
generated
|
@ -564,6 +564,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"discord": MessageLookupByLibrary.simpleMessage("Discord"),
|
||||
"dismiss": MessageLookupByLibrary.simpleMessage("Dismiss"),
|
||||
"distanceInKMUnit": MessageLookupByLibrary.simpleMessage("km"),
|
||||
"doNotSignOut": MessageLookupByLibrary.simpleMessage("Do not sign out"),
|
||||
"doThisLater": MessageLookupByLibrary.simpleMessage("Do this later"),
|
||||
"doYouWantToDiscardTheEditsYouHaveMade":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
|
@ -1208,6 +1209,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Shared with you"),
|
||||
"sharing": MessageLookupByLibrary.simpleMessage("Sharing..."),
|
||||
"showMemories": MessageLookupByLibrary.simpleMessage("Show memories"),
|
||||
"signOutFromOtherDevices":
|
||||
MessageLookupByLibrary.simpleMessage("Sign out from other devices"),
|
||||
"signOutOtherBody": MessageLookupByLibrary.simpleMessage(
|
||||
"If you think someone might know your password, you can force all other devices using your account to sign out."),
|
||||
"signOutOtherDevices":
|
||||
MessageLookupByLibrary.simpleMessage("Sign out other devices"),
|
||||
"signUpTerms": MessageLookupByLibrary.simpleMessage(
|
||||
"I agree to the <u-terms>terms of service</u-terms> and <u-policy>privacy policy</u-policy>"),
|
||||
"singleFileDeleteFromDevice": m49,
|
||||
|
|
40
lib/generated/l10n.dart
generated
40
lib/generated/l10n.dart
generated
|
@ -8097,6 +8097,46 @@ class S {
|
|||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Sign out from other devices`
|
||||
String get signOutFromOtherDevices {
|
||||
return Intl.message(
|
||||
'Sign out from other devices',
|
||||
name: 'signOutFromOtherDevices',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `If you think someone might know your password, you can force all other devices using your account to sign out.`
|
||||
String get signOutOtherBody {
|
||||
return Intl.message(
|
||||
'If you think someone might know your password, you can force all other devices using your account to sign out.',
|
||||
name: 'signOutOtherBody',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Sign out other devices`
|
||||
String get signOutOtherDevices {
|
||||
return Intl.message(
|
||||
'Sign out other devices',
|
||||
name: 'signOutOtherDevices',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Do not sign out`
|
||||
String get doNotSignOut {
|
||||
return Intl.message(
|
||||
'Do not sign out',
|
||||
name: 'doNotSignOut',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||
|
|
|
@ -1152,5 +1152,10 @@
|
|||
},
|
||||
"contacts": "Contacts",
|
||||
"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"
|
||||
}
|
|
@ -502,6 +502,7 @@ class UserService {
|
|||
Future<void> registerOrUpdateSrp(
|
||||
Uint8List loginKey, {
|
||||
SetKeysRequest? setKeysRequest,
|
||||
bool logOutOtherDevices = false,
|
||||
}) async {
|
||||
try {
|
||||
final String username = const Uuid().v4().toString();
|
||||
|
@ -558,6 +559,7 @@ class UserService {
|
|||
'setupID': setupSRPResponse.setupID,
|
||||
'srpM1': base64Encode(SRP6Util.encodeBigInt(clientM!)),
|
||||
'updatedKeyAttr': setKeysRequest.toMap(),
|
||||
'logOutOtherDevices': logOutOtherDevices,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -676,8 +678,9 @@ class UserService {
|
|||
|
||||
Future<void> updateKeyAttributes(
|
||||
KeyAttributes keyAttributes,
|
||||
Uint8List loginKey,
|
||||
) async {
|
||||
Uint8List loginKey, {
|
||||
required bool logoutOtherDevices,
|
||||
}) async {
|
||||
try {
|
||||
final setKeyRequest = SetKeysRequest(
|
||||
kekSalt: keyAttributes.kekSalt,
|
||||
|
@ -686,7 +689,11 @@ class UserService {
|
|||
memLimit: keyAttributes.memLimit!,
|
||||
opsLimit: keyAttributes.opsLimit!,
|
||||
);
|
||||
await registerOrUpdateSrp(loginKey, setKeysRequest: setKeyRequest);
|
||||
await registerOrUpdateSrp(
|
||||
loginKey,
|
||||
setKeysRequest: setKeyRequest,
|
||||
logOutOtherDevices: logoutOtherDevices,
|
||||
);
|
||||
await _config.setKeyAttributes(keyAttributes);
|
||||
} catch (e) {
|
||||
_logger.severe(e);
|
||||
|
|
|
@ -7,11 +7,13 @@ import 'package:photos/core/event_bus.dart';
|
|||
import 'package:photos/events/account_configured_event.dart';
|
||||
import 'package:photos/events/subscription_purchased_event.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import "package:photos/l10n/l10n.dart";
|
||||
import "package:photos/models/key_gen_result.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/account/recovery_key_page.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
import 'package:photos/ui/common/web_page.dart';
|
||||
import "package:photos/ui/components/models/button_type.dart";
|
||||
import 'package:photos/ui/payment/subscription.dart';
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
import 'package:photos/utils/navigation_util.dart';
|
||||
|
@ -27,9 +29,10 @@ 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();
|
||||
|
@ -379,13 +382,18 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
}
|
||||
|
||||
void _updatePassword() async {
|
||||
final logOutFromOthers = await logOutFromOtherDevices(context);
|
||||
final dialog =
|
||||
createProgressDialog(context, S.of(context).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, S.of(context).passwordChangedSuccessfully);
|
||||
Navigator.of(context).pop();
|
||||
|
@ -400,12 +408,33 @@ 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 dialog =
|
||||
createProgressDialog(context, S.of(context).generatingEncryptionKeys);
|
||||
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 {
|
||||
|
|
|
@ -12,7 +12,7 @@ description: ente photos application
|
|||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
|
||||
version: 0.8.2+522
|
||||
version: 0.8.3+523
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
|
Loading…
Reference in a new issue