1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-12-30 14:58:52 +00:00
comunicmobile/lib/ui/routes/settings/account_security_settings.dart

227 lines
7.4 KiB
Dart
Raw Normal View History

import 'package:comunic/helpers/account_helper.dart';
2020-04-30 16:19:01 +00:00
import 'package:comunic/helpers/settings_helper.dart';
2021-02-18 17:58:47 +00:00
import 'package:comunic/helpers/users_helper.dart';
2020-05-01 07:02:15 +00:00
import 'package:comunic/models/security_settings.dart';
2020-04-30 16:19:01 +00:00
import 'package:comunic/ui/dialogs/input_new_password_dialog.dart';
2020-04-30 11:32:22 +00:00
import 'package:comunic/ui/dialogs/input_user_password_dialog.dart';
2020-05-02 13:32:06 +00:00
import 'package:comunic/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart';
2021-02-18 17:58:47 +00:00
import 'package:comunic/ui/widgets/new_password_input_widget.dart';
2021-02-12 21:36:22 +00:00
import 'package:comunic/ui/widgets/settings/header_spacer_section.dart';
2021-02-18 17:58:47 +00:00
import 'package:comunic/utils/account_utils.dart';
2021-04-27 07:44:11 +00:00
import 'package:comunic/utils/flutter_utils.dart';
2020-04-29 15:28:47 +00:00
import 'package:comunic/utils/intl_utils.dart';
2020-04-30 16:19:01 +00:00
import 'package:comunic/utils/ui_utils.dart';
2020-04-29 15:28:47 +00:00
import 'package:flutter/material.dart';
2020-04-30 11:32:22 +00:00
import 'package:settings_ui/settings_ui.dart';
2020-04-29 15:28:47 +00:00
/// Account security settings
///
/// @author Pierre HUBERT
2020-05-13 16:12:45 +00:00
class AccountSecuritySettingsScreen extends StatefulWidget {
2020-04-29 15:28:47 +00:00
@override
2020-05-13 16:12:45 +00:00
_AccountSecuritySettingsScreenState createState() =>
_AccountSecuritySettingsScreenState();
2020-04-30 11:32:22 +00:00
}
2020-05-13 16:12:45 +00:00
class _AccountSecuritySettingsScreenState
extends State<AccountSecuritySettingsScreen> {
2020-04-30 11:32:22 +00:00
@override
Widget build(BuildContext context) {
return SettingsList(
sections: [
2021-02-12 21:36:22 +00:00
HeadSpacerSection(),
2020-04-30 11:32:22 +00:00
SettingsSection(
title: tr("Password"),
tiles: [
SettingsTile(
title: tr("Change password"),
2021-02-12 21:36:22 +00:00
onPressed: (_) => _changePassword(),
2020-04-30 11:32:22 +00:00
),
2020-05-01 07:02:15 +00:00
SettingsTile(
title: tr("Change your security questions"),
2021-04-27 07:44:11 +00:00
subtitle: isIOS
? null
: tr(
"Your security questions can be used to recover an access to your account when you loose your password..."),
2021-02-12 21:36:22 +00:00
onPressed: (_) => _changeSecurityQuestions(),
2021-04-17 06:40:33 +00:00
subtitleMaxLines: 3,
2020-05-01 07:02:15 +00:00
),
SettingsTile(
title: tr("Disconnect all your devices"),
2021-04-27 07:44:11 +00:00
subtitle: isIOS
? null
: tr(
"Disconnect all your devices from Comunic, including the current one. Use this option if one of the device you use for Comunic was stolen."),
2021-02-12 21:36:22 +00:00
onPressed: (_) => _disconnectAllDevices(),
2021-04-17 06:40:33 +00:00
subtitleMaxLines: 6,
),
2020-04-30 11:32:22 +00:00
],
)
],
);
}
/// Change current user password
void _changePassword() async {
2020-04-30 16:19:01 +00:00
try {
2021-02-18 17:58:47 +00:00
final currEmail = await AccountHelper.getCurrentAccountEmailAddress();
final currUser = await UsersHelper().getSingleWithThrow(userID());
2020-04-30 16:19:01 +00:00
final currPassword = await showUserPasswordDialog(context);
if (currPassword == null) return;
2021-02-18 17:58:47 +00:00
final newPassword = await showInputNewPassword(
context: context,
userInfo: UserInfoForPassword(
firstName: currUser.firstName,
lastName: currUser.lastName,
email: currEmail,
),
);
2020-04-30 16:19:01 +00:00
if (newPassword == null) return;
await SettingsHelper.changePassword(currPassword, newPassword);
showSimpleSnack(
context, tr("Your password has been successfully changed!"));
} catch (e, stack) {
print("Could not update current user password! $e\n$stack");
showSimpleSnack(context, tr("Could not update password!"));
}
2020-04-30 11:32:22 +00:00
}
2020-05-01 07:02:15 +00:00
/// 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!"));
}
}
/// Disconnect all devices
void _disconnectAllDevices() async {
try {
if (!await showConfirmDialog(
context: context,
message: tr(
"Do you really want to disconnect all your devices from Comunic ?")))
return;
await AccountHelper.disconnectAllDevices();
} catch (e, stack) {
print("Could not disconnect user on all devices! $e\n$stack");
showSimpleSnack(
context, tr("Could not disconnect you from all your devices!"));
}
}
2020-05-01 07:02:15 +00:00
}
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,
),
);
}
2020-04-30 11:32:22 +00:00
}