2023-03-25 14:29:28 +01:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:outbag_app/backend/crypto.dart';
|
|
|
|
import 'package:outbag_app/backend/request.dart';
|
|
|
|
import 'package:outbag_app/backend/user.dart';
|
|
|
|
import 'package:outbag_app/tools/fetch_wrapper.dart';
|
|
|
|
import 'package:outbag_app/tools/snackbar.dart';
|
2023-03-29 15:14:27 +02:00
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
2023-03-25 17:18:46 +01:00
|
|
|
import 'package:provider/provider.dart';
|
2023-03-25 14:29:28 +01:00
|
|
|
|
|
|
|
class ChangePasswordDialog extends StatefulWidget {
|
|
|
|
const ChangePasswordDialog({super.key});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<StatefulWidget> createState() => _ChangePasswordDialogState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ChangePasswordDialogState extends State<ChangePasswordDialog> {
|
|
|
|
final TextEditingController _ctrOldPassword = TextEditingController();
|
|
|
|
final TextEditingController _ctrNewPassword = TextEditingController();
|
|
|
|
final TextEditingController _ctrNewPasswordRepeat = TextEditingController();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return AlertDialog(
|
2023-03-29 15:14:27 +02:00
|
|
|
title: Text(AppLocalizations.of(context)!.changeThemeTitle),
|
2023-03-25 14:29:28 +01:00
|
|
|
icon: const Icon(Icons.password),
|
|
|
|
content: SingleChildScrollView(
|
2023-03-29 15:14:27 +02:00
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.all(8),
|
|
|
|
child: TextField(
|
|
|
|
controller: _ctrOldPassword,
|
|
|
|
keyboardType: TextInputType.visiblePassword,
|
|
|
|
obscureText: true,
|
|
|
|
decoration: InputDecoration(
|
|
|
|
prefixIcon: const Icon(Icons.lock),
|
|
|
|
labelText: AppLocalizations.of(context)!.inputOldPasswordLabel,
|
|
|
|
hintText: AppLocalizations.of(context)!.inputOldPasswordHint,
|
|
|
|
helperText:AppLocalizations.of(context)!.inputOldPasswordHelp,
|
|
|
|
border: const OutlineInputBorder(),
|
|
|
|
),
|
2023-03-25 14:29:28 +01:00
|
|
|
),
|
|
|
|
),
|
2023-03-29 15:14:27 +02:00
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.all(8),
|
|
|
|
child: TextField(
|
|
|
|
controller: _ctrNewPassword,
|
|
|
|
keyboardType: TextInputType.visiblePassword,
|
|
|
|
obscureText: true,
|
|
|
|
decoration: InputDecoration(
|
|
|
|
prefixIcon: const Icon(Icons.lock),
|
|
|
|
labelText: AppLocalizations.of(context)!.inputNewPasswordLabel,
|
|
|
|
hintText: AppLocalizations.of(context)!.inputNewPasswordHint,
|
|
|
|
helperText:AppLocalizations.of(context)!.inputNewPasswordHelp,
|
|
|
|
border: const OutlineInputBorder(),
|
|
|
|
),
|
2023-03-25 14:29:28 +01:00
|
|
|
),
|
|
|
|
),
|
2023-03-29 15:14:27 +02:00
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.all(8),
|
|
|
|
child: TextField(
|
|
|
|
controller: _ctrNewPasswordRepeat,
|
|
|
|
keyboardType: TextInputType.visiblePassword,
|
|
|
|
obscureText: true,
|
|
|
|
decoration: InputDecoration(
|
|
|
|
prefixIcon: const Icon(Icons.lock),
|
|
|
|
labelText: AppLocalizations.of(context)!.inputNewPasswordRepeatLabel,
|
|
|
|
hintText: AppLocalizations.of(context)!.inputNewPasswordRepeatHint,
|
|
|
|
helperText:AppLocalizations.of(context)!.inputNewPasswordRepeatHelp,
|
|
|
|
border: const OutlineInputBorder(),
|
|
|
|
),
|
2023-03-25 14:29:28 +01:00
|
|
|
),
|
|
|
|
),
|
2023-03-29 15:14:27 +02:00
|
|
|
],
|
2023-03-25 14:29:28 +01:00
|
|
|
)),
|
|
|
|
actions: [
|
|
|
|
TextButton(
|
|
|
|
onPressed: () {
|
|
|
|
// close popup
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
2023-03-29 15:14:27 +02:00
|
|
|
child: Text(AppLocalizations.of(context)!.cancel),
|
2023-03-25 14:29:28 +01:00
|
|
|
),
|
|
|
|
FilledButton(
|
|
|
|
onPressed: () async {
|
|
|
|
final scaffMgr = ScaffoldMessenger.of(context);
|
|
|
|
final nav = Navigator.of(context);
|
2023-03-25 17:18:46 +01:00
|
|
|
final user = context.read<User>();
|
2023-03-29 15:14:27 +02:00
|
|
|
final trans = AppLocalizations.of(context);
|
2023-03-25 14:29:28 +01:00
|
|
|
|
|
|
|
// validate password
|
|
|
|
if (_ctrNewPassword.text.length < 6) {
|
|
|
|
// password has to be at least 6 characters long
|
|
|
|
showSimpleSnackbar(scaffMgr,
|
2023-03-29 15:14:27 +02:00
|
|
|
text: trans!.errorPasswordLength,
|
|
|
|
action: trans.dismiss);
|
2023-03-25 14:29:28 +01:00
|
|
|
|
|
|
|
_ctrNewPasswordRepeat.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (_ctrNewPassword.text != _ctrNewPasswordRepeat.text) {
|
|
|
|
// new passwords do not match
|
|
|
|
showSimpleSnackbar(scaffMgr,
|
2023-03-29 15:14:27 +02:00
|
|
|
text: trans!.errorPasswordsDoNotMatch, action: trans.dismiss);
|
2023-03-25 14:29:28 +01:00
|
|
|
|
|
|
|
_ctrNewPasswordRepeat.clear();
|
|
|
|
return;
|
|
|
|
}
|
2023-03-25 17:18:46 +01:00
|
|
|
if (hashPassword(_ctrOldPassword.text) != user.password) {
|
2023-03-25 14:29:28 +01:00
|
|
|
// current password wrong
|
|
|
|
showSimpleSnackbar(scaffMgr,
|
2023-03-29 15:14:27 +02:00
|
|
|
text: trans!.errorOldPasswordWrong, action: trans.dismiss);
|
2023-03-25 14:29:28 +01:00
|
|
|
|
|
|
|
_ctrOldPassword.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final password = hashPassword(_ctrNewPassword.text);
|
|
|
|
|
|
|
|
// send request
|
|
|
|
doNetworkRequest(scaffMgr,
|
2023-03-29 15:14:27 +02:00
|
|
|
req: () => postWithCreadentials(
|
|
|
|
path: 'changePassword',
|
|
|
|
target: user.server,
|
|
|
|
body: {'accountKey': password},
|
|
|
|
credentials: user),
|
|
|
|
onOK: (_) async {
|
|
|
|
// update local user struct
|
|
|
|
final updatedUser = User(
|
|
|
|
username: user.username,
|
|
|
|
password: password,
|
|
|
|
server: user.server);
|
|
|
|
await updatedUser.toDisk();
|
|
|
|
},
|
|
|
|
after: () {
|
|
|
|
// close popup
|
|
|
|
nav.pop();
|
|
|
|
});
|
2023-03-25 14:29:28 +01:00
|
|
|
},
|
2023-03-29 15:14:27 +02:00
|
|
|
child: Text(AppLocalizations.of(context)!.changeThemeTitle),
|
2023-03-25 14:29:28 +01:00
|
|
|
)
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|