1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-12-26 04:48:51 +00:00

Can change password

This commit is contained in:
Pierre HUBERT 2020-05-03 16:55:00 +02:00
parent 44ea647624
commit 11c25ea271
3 changed files with 156 additions and 1 deletions

View File

@ -158,6 +158,24 @@ class AccountHelper {
.execWithThrow())
.getObject()["reset_token"];
/// Check a password reset token
///
/// Throws in case failure
static Future<void> validatePasswordResetToken(String token) async =>
await APIRequest.withoutLogin("account/check_password_reset_token")
.addString("token", token)
.execWithThrow();
/// Change account password using password reset token
///
/// Throws an exception in case of failure
static Future<void> changeAccountPassword(
String token, String password) async =>
await APIRequest.withoutLogin("account/reset_user_passwd")
.addString("token", token)
.addString("password", password)
.execWithThrow();
/// Get current user ID from the server
Future<int> _downloadCurrentUserID() async {
final response = await APIRequest(

View File

@ -0,0 +1,129 @@
import 'package:comunic/helpers/account_helper.dart';
import 'package:comunic/ui/dialogs/input_new_password_dialog.dart';
import 'package:comunic/ui/widgets/async_screen_widget.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
/// Reset user password route
///
/// @author Pierre HUBERT
class PasswordResetRoute extends StatelessWidget {
final String token;
const PasswordResetRoute({
Key key,
@required this.token,
}) : assert(token != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(tr("Change your password")),
),
body: _PasswordResetBody(token: token),
);
}
}
class _PasswordResetBody extends StatefulWidget {
final String token;
const _PasswordResetBody({Key key, @required this.token})
: assert(token != null),
super(key: key);
@override
__PasswordResetBodyState createState() => __PasswordResetBodyState();
}
enum _Status { BEFORE_CHANGE, WHILE_CHANGE, AFTER_CHANGE }
class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
final _key = GlobalKey<AsyncScreenWidgetState>();
var _status = _Status.BEFORE_CHANGE;
void _setStatus(_Status s) => setState(() => _status = s);
Future<void> _validateToken() async {
_status = _Status.BEFORE_CHANGE;
await AccountHelper.validatePasswordResetToken(widget.token);
}
@override
Widget build(BuildContext context) {
return AsyncScreenWidget(
key: _key,
onReload: _validateToken, // The first time, we validate the token
onBuild: _buildBody,
errorMessage: tr(
"Could not validate your password reset token! Maybe it has expired now..."),
);
}
Widget _buildBody() {
// The user has not requested yet to change his password
if (_status == _Status.BEFORE_CHANGE)
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(tr("You can choose a new password.")),
OutlineButton(
onPressed: _changePassword,
child: Text(tr("Choose a new password")),
)
],
));
// Password is being changed
if (_status == _Status.WHILE_CHANGE) return buildCenteredProgressBar();
// Password was successfully changed!
if (_status == _Status.AFTER_CHANGE)
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
tr("Congratulations! Your password has now been successfully changed!"),
textAlign: TextAlign.center,
),
OutlineButton(
onPressed: _quitScreen,
child: Text(tr("Login")),
)
],
));
throw Exception("Unreachable statement!");
}
/// Ask the user to specify his new password
void _changePassword() async {
try {
// Ask for new password
final newPass = await showInputNewPassword(context);
if (newPass == null) return;
_setStatus(_Status.WHILE_CHANGE);
// Apply it
await AccountHelper.changeAccountPassword(widget.token, newPass);
_setStatus(_Status.AFTER_CHANGE);
} catch (e, s) {
print("Could not change user password! $e\n$s");
showSimpleSnack(context, tr("Could not change your password!"));
// We start everything again
_key.currentState.refresh();
}
}
/// Go back to login screen
void _quitScreen() => Navigator.of(context).pop();
}

View File

@ -1,4 +1,5 @@
import 'package:comunic/helpers/account_helper.dart';
import 'package:comunic/ui/routes/password_reset_route.dart';
import 'package:comunic/ui/widgets/dialogs/cancel_dialog_button.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/input_utils.dart';
@ -80,6 +81,8 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
case _SelectedOption.SECURITY_QUESTIONS:
return _buildSecurityQuestionsScreen();
}
throw Exception("Unreachable statement!");
}
Widget _buildEnterEmailAddressScreen() {
@ -225,7 +228,8 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
_setLoading(true);
try {
final token = await AccountHelper.checkAnswers(_emailAddress, _answers);
print(token);
_useResetToken(token);
} catch (e, s) {
print("Could not submit security answers! $e\n$s");
showSimpleSnack(
@ -233,6 +237,10 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
}
_setLoading(false);
}
/// Call this method whenever the user managed to get a password reset token
void _useResetToken(String token) => Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (c) => PasswordResetRoute(token: token)));
}
class _Spacer extends StatelessWidget {