mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 12:59:21 +00:00
Can change security settings
This commit is contained in:
parent
289bf30a40
commit
20ea964337
@ -5,6 +5,7 @@ import 'package:comunic/models/account_image_settings.dart';
|
|||||||
import 'package:comunic/models/api_request.dart';
|
import 'package:comunic/models/api_request.dart';
|
||||||
import 'package:comunic/models/general_settings.dart';
|
import 'package:comunic/models/general_settings.dart';
|
||||||
import 'package:comunic/models/new_emoji.dart';
|
import 'package:comunic/models/new_emoji.dart';
|
||||||
|
import 'package:comunic/models/security_settings.dart';
|
||||||
|
|
||||||
/// Settings helper
|
/// Settings helper
|
||||||
///
|
///
|
||||||
@ -161,4 +162,36 @@ class SettingsHelper {
|
|||||||
.addString("oldPassword", oldPassword)
|
.addString("oldPassword", oldPassword)
|
||||||
.addString("newPassword", newPassword)
|
.addString("newPassword", newPassword)
|
||||||
.execWithThrow();
|
.execWithThrow();
|
||||||
|
|
||||||
|
/// Retrieve security settings of the user
|
||||||
|
///
|
||||||
|
/// This method throws in case of failure
|
||||||
|
static Future<SecuritySettings> getSecuritySettings(String password) async {
|
||||||
|
final response =
|
||||||
|
(await APIRequest(uri: "settings/get_security", needLogin: true)
|
||||||
|
.addString("password", password)
|
||||||
|
.execWithThrow())
|
||||||
|
.getObject();
|
||||||
|
|
||||||
|
return SecuritySettings(
|
||||||
|
securityQuestion1: response["security_question_1"],
|
||||||
|
securityAnswer1: response["security_answer_1"],
|
||||||
|
securityQuestion2: response["security_question_2"],
|
||||||
|
securityAnswer2: response["security_answer_2"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply new security settings to the user
|
||||||
|
///
|
||||||
|
/// Throws in case of failure
|
||||||
|
static Future<void> setSecuritySettings(
|
||||||
|
String password, SecuritySettings newSettings) async {
|
||||||
|
await APIRequest(uri: "settings/set_security", needLogin: true)
|
||||||
|
.addString("password", password)
|
||||||
|
.addString("security_question_1", newSettings.securityQuestion1)
|
||||||
|
.addString("security_answer_1", newSettings.securityAnswer1)
|
||||||
|
.addString("security_question_2", newSettings.securityQuestion2)
|
||||||
|
.addString("security_answer_2", newSettings.securityAnswer2)
|
||||||
|
.execWithThrow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
22
lib/models/security_settings.dart
Normal file
22
lib/models/security_settings.dart
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Security settings of the user
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
class SecuritySettings {
|
||||||
|
final String securityQuestion1;
|
||||||
|
final String securityAnswer1;
|
||||||
|
final String securityQuestion2;
|
||||||
|
final String securityAnswer2;
|
||||||
|
|
||||||
|
const SecuritySettings({
|
||||||
|
@required this.securityQuestion1,
|
||||||
|
@required this.securityAnswer1,
|
||||||
|
@required this.securityQuestion2,
|
||||||
|
@required this.securityAnswer2,
|
||||||
|
}) : assert(securityQuestion1 != null),
|
||||||
|
assert(securityAnswer1 != null),
|
||||||
|
assert(securityQuestion2 != null),
|
||||||
|
assert(securityAnswer2 != null);
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:comunic/helpers/settings_helper.dart';
|
import 'package:comunic/helpers/settings_helper.dart';
|
||||||
|
import 'package:comunic/models/security_settings.dart';
|
||||||
import 'package:comunic/ui/dialogs/input_new_password_dialog.dart';
|
import 'package:comunic/ui/dialogs/input_new_password_dialog.dart';
|
||||||
import 'package:comunic/ui/dialogs/input_user_password_dialog.dart';
|
import 'package:comunic/ui/dialogs/input_user_password_dialog.dart';
|
||||||
|
import 'package:comunic/ui/widgets/auto_sized_dialog_content_widget.dart';
|
||||||
import 'package:comunic/utils/intl_utils.dart';
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
import 'package:comunic/utils/ui_utils.dart';
|
import 'package:comunic/utils/ui_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -41,6 +43,12 @@ class __AccountSecuritySettingsScreenBodyState
|
|||||||
title: tr("Change password"),
|
title: tr("Change password"),
|
||||||
onTap: _changePassword,
|
onTap: _changePassword,
|
||||||
),
|
),
|
||||||
|
SettingsTile(
|
||||||
|
title: tr("Change your security questions"),
|
||||||
|
subtitle: tr(
|
||||||
|
"Your security questions can be used to recover an access to your account when you loose your password..."),
|
||||||
|
onTap: _changeSecurityQuestions,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -67,4 +75,118 @@ class __AccountSecuritySettingsScreenBodyState
|
|||||||
showSimpleSnack(context, tr("Could not update password!"));
|
showSimpleSnack(context, tr("Could not update password!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Change security questions
|
||||||
|
void _changeSecurityQuestions() async {
|
||||||
|
try {
|
||||||
|
final password = await showUserPasswordDialog(context);
|
||||||
|
|
||||||
|
if (password == null) return;
|
||||||
|
|
||||||
|
final settings = await SettingsHelper.getSecuritySettings(password);
|
||||||
|
|
||||||
|
final newSettings = await showDialog<SecuritySettings>(
|
||||||
|
context: context,
|
||||||
|
builder: (c) => _SecurityQuestionsDialog(settings: settings));
|
||||||
|
|
||||||
|
if (newSettings == null) return;
|
||||||
|
|
||||||
|
await SettingsHelper.setSecuritySettings(password, newSettings);
|
||||||
|
|
||||||
|
showSimpleSnack(context,
|
||||||
|
tr("You security questions have been successfully updated!"));
|
||||||
|
} catch (e, stack) {
|
||||||
|
print("Could not update security questions!$e\n$stack");
|
||||||
|
showSimpleSnack(context, tr("Could not update security questions!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SecurityQuestionsDialog extends StatefulWidget {
|
||||||
|
final SecuritySettings settings;
|
||||||
|
|
||||||
|
const _SecurityQuestionsDialog({Key key, @required this.settings})
|
||||||
|
: assert(settings != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
__SecurityQuestionsDialogState createState() =>
|
||||||
|
__SecurityQuestionsDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> {
|
||||||
|
TextEditingController _controllerQuestion1;
|
||||||
|
TextEditingController _controllerAnswer1;
|
||||||
|
TextEditingController _controllerQuestion2;
|
||||||
|
TextEditingController _controllerAnswer2;
|
||||||
|
|
||||||
|
SecuritySettings get _newSettings => SecuritySettings(
|
||||||
|
securityQuestion1: _controllerQuestion1.text,
|
||||||
|
securityAnswer1: _controllerAnswer1.text,
|
||||||
|
securityQuestion2: _controllerQuestion2.text,
|
||||||
|
securityAnswer2: _controllerAnswer2.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_controllerQuestion1 =
|
||||||
|
TextEditingController(text: widget.settings.securityQuestion1);
|
||||||
|
_controllerAnswer1 =
|
||||||
|
TextEditingController(text: widget.settings.securityAnswer1);
|
||||||
|
_controllerQuestion2 =
|
||||||
|
TextEditingController(text: widget.settings.securityQuestion2);
|
||||||
|
_controllerAnswer2 =
|
||||||
|
TextEditingController(text: widget.settings.securityAnswer2);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(tr("Update security questions")),
|
||||||
|
content: AutoSizeDialogContentWidget(child: _buildContent()),
|
||||||
|
actions: <Widget>[
|
||||||
|
MaterialButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(tr("Cancel").toUpperCase()),
|
||||||
|
),
|
||||||
|
MaterialButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(_newSettings),
|
||||||
|
child: Text(tr("Update").toUpperCase()),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildContent() {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(tr(
|
||||||
|
"Note: Your two questions and answers MUST be completed in order to be able to recover your account using your security questions!")),
|
||||||
|
_buildTextField(
|
||||||
|
controller: _controllerQuestion1, label: tr("Question 1")),
|
||||||
|
_buildTextField(controller: _controllerAnswer1, label: tr("Answer 1")),
|
||||||
|
_buildTextField(
|
||||||
|
controller: _controllerQuestion2, label: tr("Question 2")),
|
||||||
|
_buildTextField(controller: _controllerAnswer2, label: tr("Answer 2")),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextField({
|
||||||
|
@required TextEditingController controller,
|
||||||
|
@required String label,
|
||||||
|
}) {
|
||||||
|
return TextField(
|
||||||
|
controller: controller,
|
||||||
|
onChanged: (s) => setState(() {}),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
labelText: label,
|
||||||
|
errorText: controller.text.isNotEmpty && controller.text.length < 5
|
||||||
|
? tr("Unsafe value!")
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user