2FA reset via SMS

This commit is contained in:
Hillel Coren 2022-11-07 18:01:28 +02:00
parent aa486ab314
commit 00b979c731
3 changed files with 155 additions and 63 deletions

View File

@ -77,6 +77,7 @@ class _LoginState extends State<LoginView> {
bool _createAccount = false;
bool _recoverPassword = false;
bool _disable2FA = false;
bool _termsChecked = false;
bool _privacyChecked = false;
@ -235,6 +236,7 @@ class _LoginState extends State<LoginView> {
_loginError = '';
if (_recoverPassword) {
_recoverPassword = false;
_disable2FA = false;
_buttonController.reset();
showDialog<MessageDialog>(
context: context,
@ -269,6 +271,14 @@ class _LoginState extends State<LoginView> {
url: url,
secret: _isSelfHosted ? _secretController.text : '',
);
} else if (_disable2FA) {
viewModel.onDisable2FAPressed(
context,
completer,
email: _emailController.text,
url: url,
secret: _isSelfHosted ? _secretController.text : '',
);
} else {
viewModel.onLoginPressed(
context,
@ -599,24 +609,29 @@ class _LoginState extends State<LoginView> {
),
SizedBox(width: 10),
Text(
_recoverPassword
? localization.recoverPassword
: _createAccount
? (_loginType == LOGIN_TYPE_EMAIL
? localization.emailSignUp
: _loginType ==
LOGIN_TYPE_MICROSOFT
? localization
.microsoftSignUp
: localization.googleSignUp)
: (_loginType == LOGIN_TYPE_EMAIL
? localization.emailSignIn
: _loginType ==
LOGIN_TYPE_MICROSOFT
? localization
.microsoftSignIn
: localization
.googleSignIn),
_disable2FA
? localization.disable2fa
: _recoverPassword
? localization.recoverPassword
: _createAccount
? (_loginType ==
LOGIN_TYPE_EMAIL
? localization.emailSignUp
: _loginType ==
LOGIN_TYPE_MICROSOFT
? localization
.microsoftSignUp
: localization
.googleSignUp)
: (_loginType ==
LOGIN_TYPE_EMAIL
? localization.emailSignIn
: _loginType ==
LOGIN_TYPE_MICROSOFT
? localization
.microsoftSignIn
: localization
.googleSignIn),
style: TextStyle(
fontSize: 18, color: Colors.white),
)
@ -662,11 +677,34 @@ class _LoginState extends State<LoginView> {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
if (!_createAccount)
if (_recoverPassword) ...[
if (!_disable2FA)
InkWell(
onTap: () {
setState(() {
_disable2FA = true;
});
},
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.lock, size: 16),
SizedBox(width: 8),
Text(localization.disable2fa),
]),
),
),
InkWell(
onTap: () {
setState(() {
_recoverPassword = !_recoverPassword;
if (_disable2FA) {
_disable2FA = false;
} else {
_recoverPassword = false;
}
});
},
child: Padding(
@ -675,67 +713,88 @@ class _LoginState extends State<LoginView> {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (!_recoverPassword)
Icon(MdiIcons.lock, size: 16),
Icon(Icons.cancel, size: 16),
SizedBox(width: 8),
Text(_recoverPassword
? localization.cancel
: localization.recoverPassword),
Text(localization.cancel),
]),
),
),
if (!_recoverPassword && !_isSelfHosted)
InkWell(
onTap: () {
launchUrl(Uri.parse(kStatusCheckUrl));
},
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.security, size: 16),
SizedBox(width: 8),
Text(localization.checkStatus)
],
] else ...[
if (!_createAccount)
InkWell(
onTap: () {
setState(() {
_recoverPassword = true;
});
},
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (!_recoverPassword)
Icon(MdiIcons.lock, size: 16),
SizedBox(width: 8),
Text(_recoverPassword
? localization.cancel
: localization.recoverPassword),
]),
),
),
),
if (!_recoverPassword)
if (kIsWeb)
if (!_recoverPassword && !_isSelfHosted)
InkWell(
onTap: () =>
launchUrl(Uri.parse(getNativeAppUrl(platform))),
onTap: () {
launchUrl(Uri.parse(kStatusCheckUrl));
},
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(getNativeAppIcon(platform), size: 16),
Icon(Icons.security, size: 16),
SizedBox(width: 8),
Text('$platform ${localization.app}')
Text(localization.checkStatus)
],
),
),
)
else
InkWell(
onTap: () => launchUrl(Uri.parse(kDocsUrl)),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.book, size: 16),
SizedBox(width: 8),
Text(localization.documentation)
],
),
if (!_recoverPassword)
if (kIsWeb)
InkWell(
onTap: () =>
launchUrl(Uri.parse(getNativeAppUrl(platform))),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(getNativeAppIcon(platform), size: 16),
SizedBox(width: 8),
Text('$platform ${localization.app}')
],
),
),
),
)
)
else
InkWell(
onTap: () => launchUrl(Uri.parse(kDocsUrl)),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.book, size: 16),
SizedBox(width: 8),
Text(localization.documentation)
],
),
),
)
]
],
),
],

View File

@ -57,6 +57,7 @@ class LoginVM {
@required this.authState,
@required this.onLoginPressed,
@required this.onRecoverPressed,
@required this.onDisable2FAPressed,
@required this.onSignUpPressed,
@required this.onGoogleLoginPressed,
@required this.onGoogleSignUpPressed,
@ -89,6 +90,14 @@ class LoginVM {
@required String secret,
}) onRecoverPressed;
final Function(
BuildContext,
Completer<Null> completer, {
@required String email,
@required String url,
@required String secret,
}) onDisable2FAPressed;
final Function(
BuildContext,
Completer<Null> completer, {
@ -376,6 +385,24 @@ class LoginVM {
secret: secret.trim(),
));
},
onDisable2FAPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String url,
@required String secret,
}) async {
if (store.state.isLoading) {
return;
}
store.dispatch(RecoverPasswordRequest(
completer: completer,
email: email.trim(),
url: _formatApiUrl(url),
secret: secret.trim(),
));
},
onLoginPressed: (
BuildContext context,
Completer<Null> completer, {

View File

@ -16,6 +16,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'disable_2fa': 'Disable 2FA',
'change_number': 'Change Number',
'resend_code': 'Resend Code',
'base_type': 'Base Type',
@ -87487,6 +87488,11 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['change_number'] ??
_localizedValues['en']['change_number'];
String get disable2fa =>
_localizedValues[localeCode]['disable_2fa'] ??
_localizedValues['en']['disable_2fa'];
// STARTER: lang field - do not remove comment
String lookup(String key) {