1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-29 16:26:27 +00:00
comunicmobile/lib/ui/routes/settings/account_security_settings.dart

226 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';
2021-12-28 14:23:08 +00:00
import 'package:flutter_settings_ui/flutter_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!")!);
2020-04-30 16:19:01 +00:00
} catch (e, stack) {
print("Could not update current user password! $e\n$stack");
showSimpleSnack(context, tr("Could not update password!")!);
2020-04-30 16:19:01 +00:00
}
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!")!);
2020-05-01 07:02:15 +00:00
} catch (e, stack) {
print("Could not update security questions!$e\n$stack");
showSimpleSnack(context, tr("Could not update security questions!")!);
2020-05-01 07:02:15 +00:00
}
}
/// 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})
2022-03-11 16:02:06 +00:00
: super(key: key);
2020-05-01 07:02:15 +00:00
@override
__SecurityQuestionsDialogState createState() =>
__SecurityQuestionsDialogState();
}
class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> {
late TextEditingController _controllerQuestion1;
late TextEditingController _controllerAnswer1;
late TextEditingController _controllerQuestion2;
late TextEditingController _controllerAnswer2;
2020-05-01 07:02:15 +00:00
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")!),
2020-05-01 07:02:15 +00:00
content: AutoSizeDialogContentWidget(child: _buildContent()),
actions: <Widget>[
MaterialButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(tr("Cancel")!.toUpperCase()),
2020-05-01 07:02:15 +00:00
),
MaterialButton(
onPressed: () => Navigator.of(context).pop(_newSettings),
child: Text(tr("Update")!.toUpperCase()),
2020-05-01 07:02:15 +00:00
)
],
);
}
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!")!),
2020-05-01 07:02:15 +00:00
_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,
2020-05-01 07:02:15 +00:00
}) {
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
}