LoginV2 changes

This commit is contained in:
Neeraj Gupta 2023-07-24 11:47:01 +05:30
parent 37ce8a55db
commit a88cd75a5c

View file

@ -1,12 +1,15 @@
import 'dart:async'; import 'dart:async';
import 'dart:typed_data';
import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/errors.dart'; import 'package:ente_auth/core/errors.dart';
import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/ui/account/recovery_page.dart'; import 'package:ente_auth/ui/account/recovery_page.dart';
import 'package:ente_auth/ui/common/dynamic_fab.dart'; import 'package:ente_auth/ui/common/dynamic_fab.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart'; import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/home_page.dart'; import 'package:ente_auth/ui/home_page.dart';
import 'package:ente_auth/utils/crypto_util.dart';
import 'package:ente_auth/utils/dialog_util.dart'; import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/email_util.dart'; import 'package:ente_auth/utils/email_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -26,11 +29,20 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
String? email; String? email;
bool _passwordInFocus = false; bool _passwordInFocus = false;
bool _passwordVisible = false; bool _passwordVisible = false;
String? _volatilePassword;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
email = Configuration.instance.getEmail(); email = Configuration.instance.getEmail();
_volatilePassword = Configuration.instance.getVolatilePassword();
if (_volatilePassword != null) {
_passwordController.text = _volatilePassword!;
Future.delayed(
Duration.zero,
() => verifyPassword(_volatilePassword!),
);
}
_passwordFocusNode.addListener(() { _passwordFocusNode.addListener(() {
setState(() { setState(() {
_passwordInFocus = _passwordFocusNode.hasFocus; _passwordInFocus = _passwordFocusNode.hasFocus;
@ -64,68 +76,13 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
), ),
body: _getBody(), body: _getBody(),
floatingActionButton: DynamicFAB( floatingActionButton: DynamicFAB(
key: const ValueKey("verifyPasswordButton"),
isKeypadOpen: isKeypadOpen, isKeypadOpen: isKeypadOpen,
isFormValid: _passwordController.text.isNotEmpty, isFormValid: _passwordController.text.isNotEmpty,
buttonText: context.l10n.verifyPassword, buttonText: context.l10n.verifyPassword,
onPressedFunction: () async { onPressedFunction: () async {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
final dialog = createProgressDialog(context, context.l10n.pleaseWait); await verifyPassword(_passwordController.text);
await dialog.show();
try {
await Configuration.instance.decryptSecretsAndGetKeyEncKey(
_passwordController.text,
Configuration.instance.getKeyAttributes()!,
);
} on KeyDerivationError catch (e, s) {
_logger.severe("Password verification failed", e, s);
await dialog.hide();
final dialogChoice = await showChoiceDialog(
context,
title: context.l10n.recreatePasswordTitle,
body: context.l10n.recreatePasswordBody,
firstButtonLabel: context.l10n.useRecoveryKey,
);
if (dialogChoice!.action == ButtonAction.first) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const RecoveryPage();
},
),
);
}
return;
} catch (e, s) {
_logger.severe("Password verification failed", e, s);
await dialog.hide();
final dialogChoice = await showChoiceDialog(
context,
title: context.l10n.incorrectPasswordTitle,
body: context.l10n.pleaseTryAgain,
firstButtonLabel: context.l10n.contactSupport,
secondButtonLabel: context.l10n.ok,
);
if (dialogChoice!.action == ButtonAction.first) {
await sendLogs(
context,
context.l10n.contactSupport,
"support@ente.io",
postShare: () {},
);
}
return;
}
await dialog.hide();
unawaited(
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext context) {
return const HomePage();
},
),
(route) => false,
),
);
}, },
), ),
floatingActionButtonLocation: fabLocation(), floatingActionButtonLocation: fabLocation(),
@ -133,6 +90,90 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
); );
} }
Future<void> verifyPassword(String password) async {
FocusScope.of(context).unfocus();
final dialog =
createProgressDialog(context, context.l10n.pleaseWait);
await dialog.show();
try {
final kek = await Configuration.instance.decryptSecretsAndGetKeyEncKey(
password,
Configuration.instance.getKeyAttributes()!,
);
_registerSRPForExistingUsers(kek).ignore();
} on KeyDerivationError catch (e, s) {
_logger.severe("Password verification failed", e, s);
await dialog.hide();
final dialogChoice = await showChoiceDialog(
context,
title: context.l10n.recreatePasswordTitle,
body: context.l10n.recreatePasswordBody,
firstButtonLabel: context.l10n.useRecoveryKey,
);
if (dialogChoice!.action == ButtonAction.first) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const RecoveryPage();
},
),
);
}
return;
} catch (e, s) {
_logger.severe("Password verification failed", e, s);
await dialog.hide();
final dialogChoice = await showChoiceDialog(
context,
title: context.l10n.incorrectPasswordTitle,
body: context.l10n.pleaseTryAgain,
firstButtonLabel: context.l10n.contactSupport,
secondButtonLabel: context.l10n.ok,
);
if (dialogChoice!.action == ButtonAction.first) {
await sendLogs(
context,
context.l10n.contactSupport,
"support@ente.io",
postShare: () {},
);
}
return;
}
await dialog.hide();
Configuration.instance.setVolatilePassword(null);
unawaited(
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext context) {
return const HomePage();
},
),
(route) => false,
),
);
}
Future<void> _registerSRPForExistingUsers(Uint8List key) async {
bool shouldSetupSRP = false;
try {
// ignore: unused_local_variable
final attr = await UserService.instance.getSrpAttributes(email!);
} on SrpSetupNotCompleteError {
shouldSetupSRP = true;
} catch (e, s) {
_logger.severe("error while fetching attr", e, s);
}
if (shouldSetupSRP) {
try {
final Uint8List loginKey = await CryptoUtil.deriveLoginKey(key);
await UserService.instance.registerOrUpdateSrp(loginKey);
} catch (e, s) {
_logger.severe("error while setting up srp for existing users", e, s);
}
}
}
Widget _getBody() { Widget _getBody() {
return Column( return Column(
children: [ children: [
@ -142,10 +183,10 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
children: [ children: [
Padding( Padding(
padding: padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 20), const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
child: Text( child: Text(
context.l10n.welcomeBack, context.l10n.welcomeBack,
style: Theme.of(context).textTheme.headline4, style: Theme.of(context).textTheme.headlineMedium,
), ),
), ),
Visibility( Visibility(
@ -165,6 +206,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
Padding( Padding(
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0), padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
child: TextFormField( child: TextFormField(
key: const ValueKey("passwordInputField"),
autofillHints: const [AutofillHints.password], autofillHints: const [AutofillHints.password],
decoration: InputDecoration( decoration: InputDecoration(
hintText: context.l10n.enterYourPasswordHint, hintText: context.l10n.enterYourPasswordHint,
@ -176,19 +218,19 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
), ),
suffixIcon: _passwordInFocus suffixIcon: _passwordInFocus
? IconButton( ? IconButton(
icon: Icon( icon: Icon(
_passwordVisible _passwordVisible
? Icons.visibility ? Icons.visibility
: Icons.visibility_off, : Icons.visibility_off,
color: Theme.of(context).iconTheme.color, color: Theme.of(context).iconTheme.color,
size: 20, size: 20,
), ),
onPressed: () { onPressed: () {
setState(() { setState(() {
_passwordVisible = !_passwordVisible; _passwordVisible = !_passwordVisible;
}); });
}, },
) )
: null, : null,
), ),
style: const TextStyle( style: const TextStyle(
@ -230,11 +272,13 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
child: Center( child: Center(
child: Text( child: Text(
context.l10n.forgotPassword, context.l10n.forgotPassword,
style: style: Theme.of(context)
Theme.of(context).textTheme.subtitle1!.copyWith( .textTheme
fontSize: 14, .titleMedium!
decoration: TextDecoration.underline, .copyWith(
), fontSize: 14,
decoration: TextDecoration.underline,
),
), ),
), ),
), ),
@ -254,11 +298,13 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
child: Center( child: Center(
child: Text( child: Text(
context.l10n.changeEmail, context.l10n.changeEmail,
style: style: Theme.of(context)
Theme.of(context).textTheme.subtitle1!.copyWith( .textTheme
fontSize: 14, .titleMedium!
decoration: TextDecoration.underline, .copyWith(
), fontSize: 14,
decoration: TextDecoration.underline,
),
), ),
), ),
), ),