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

Show security questions

This commit is contained in:
Pierre HUBERT 2020-05-03 15:35:07 +02:00
parent 91e7dd4019
commit e78d526bbb
2 changed files with 87 additions and 6 deletions

View File

@ -130,10 +130,20 @@ class AccountHelper {
/// Throws in case of failure
static Future<bool> hasSecurityQuestions(String email) async =>
(await APIRequest.withoutLogin("account/has_security_questions")
.addString("email", email)
.execWithThrow())
.addString("email", email)
.execWithThrow())
.getObject()["defined"];
/// Get the security questions of the user
///
/// Throws in case of failure
static Future<List<String>> getSecurityQuestions(String email) async =>
((await APIRequest.withoutLogin("account/get_security_questions")
.addString("email", email)
.execWithThrow())
.getObject()["questions"])
.cast<String>();
/// Get current user ID from the server
Future<int> _downloadCurrentUserID() async {
final response = await APIRequest(

View File

@ -6,6 +6,7 @@ import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
/// Reset password route
///
@ -21,14 +22,14 @@ class ResetPasswordRoute extends StatelessWidget {
body: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 300),
child: _ResetPasswordBody(),
child: SingleChildScrollView(child: _ResetPasswordBody()),
),
),
);
}
}
enum _SelectedOption { NONE }
enum _SelectedOption { NONE, SECURITY_QUESTIONS }
class _ResetPasswordBody extends StatefulWidget {
@override
@ -54,6 +55,10 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
void _setLoading(bool loading) => setState(() => _loading = loading);
/// Step 3b - Answer security questions
List<String> _questions;
var _questionsControllers = List<TextEditingController>();
@override
Widget build(BuildContext context) {
if (_loading) return buildCenteredProgressBar();
@ -63,6 +68,9 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
switch (_selectedOption) {
case _SelectedOption.NONE:
return _buildOptionsScreen();
case _SelectedOption.SECURITY_QUESTIONS:
return _buildSecurityQuestionsScreen();
}
}
@ -126,13 +134,20 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(tr("Here are your options to reset your account:")),
Container(height: 15),
_Spacer(),
OutlineButton.icon(
onPressed: _openSendEmailDialog,
icon: Icon(Icons.email),
label: Text(tr("Send us an email to ask for help")),
),
Container(height: 15),
_Spacer(visible: _hasSecurityQuestions),
_hasSecurityQuestions
? OutlineButton.icon(
onPressed: _loadSecurityQuestions,
icon: Icon(Icons.help_outline),
label: Text(tr("Answer your security questions")),
)
: Container(),
],
);
@ -146,4 +161,60 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
actions: <Widget>[CancelDialogButton()],
));
}
/// Load security questions
void _loadSecurityQuestions() async {
_setLoading(true);
try {
_questions = await AccountHelper.getSecurityQuestions(_emailAddress);
_questionsControllers =
List.generate(_questions.length, (i) => TextEditingController());
_selectedOption = _SelectedOption.SECURITY_QUESTIONS;
} catch (e, s) {
print("Could not load security questions! $e\n$s");
showSimpleSnack(context, tr("Could not load your security questions!"));
}
_setLoading(false);
}
/// Show a screen to prompt security questions of the user
Widget _buildSecurityQuestionsScreen() {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[]
..add(Text(tr("Please answer now your security questions:")))
..add(_Spacer())
..addAll(List.generate(_questions.length, _buildSecurityQuestionField))
..add(_Spacer())
..add(OutlineButton(
onPressed: null,
child: Text(tr("Submit")),
)),
);
}
Widget _buildSecurityQuestionField(int id) => TextField(
controller: _questionsControllers[id],
decoration: InputDecoration(
alignLabelWithHint: true,
labelText: _questions[id],
),
);
}
class _Spacer extends StatelessWidget {
final bool visible;
const _Spacer({Key key, this.visible = true})
: assert(visible != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: visible ? 35 : null,
);
}
}