actions-test/lib/screens/settings/dialogs/password.dart
Jakob Meier 30a19fcc1e
Started working on settings screen
Added:
- changePassword to change the password
NOTE: this requires the old password,
just to prevent account hijacking.
- some basic user limit information
- theme selector
NOTE: the system theme is meant to function like auto-theme,
and is directly translated into a flutter ThemeMode,
however, this does not appear to be working on the web.

This commit also adds the logout and delete account buttons,
but they do not yet delete all rooms,
nor do they properly logout the user.
BUG: User is not logged out correctly,
reloading the page fixes this.
Maybe localstore.listen does not detect deletion?
2023-03-25 14:29:28 +01:00

177 lines
5.6 KiB
Dart

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';
import 'package:routemaster/routemaster.dart';
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();
User? user;
void loadUser() async {
final rmaster = Routemaster.of(context);
try {
final u = await User.fromDisk();
setState(() {
user = u;
});
} catch (_) {
// logout user
await User.removeDisk();
// move to welcome screen
rmaster.replace('/');
}
}
@override
void initState() {
super.initState();
User.listen((data) async {
try {
final u = await User.fromDisk();
setState(() {
user = u;
});
} catch (_) {}
});
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Change Password'),
icon: const Icon(Icons.password),
content: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
controller: _ctrOldPassword,
keyboardType: TextInputType.visiblePassword,
obscureText: true,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.lock),
labelText: 'Old Password',
hintText: 'Your current password',
helperText:
'For safety, you have to type your current passwort',
border: OutlineInputBorder(),
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
controller: _ctrNewPassword,
keyboardType: TextInputType.visiblePassword,
obscureText: true,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.lock),
labelText: 'New Password',
hintText: 'Your new password',
helperText: 'Password have to be at least six characters long',
border: OutlineInputBorder(),
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
controller: _ctrNewPasswordRepeat,
keyboardType: TextInputType.visiblePassword,
obscureText: true,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.lock),
labelText: 'Repeat new Password',
hintText: 'Type your new password again',
helperText:
'Type your new password again, to make sure you know it',
border: OutlineInputBorder(),
),
),
),
],
)),
actions: [
TextButton(
onPressed: () {
// close popup
Navigator.of(context).pop();
},
child: const Text('Cancel'),
),
FilledButton(
onPressed: () async {
final scaffMgr = ScaffoldMessenger.of(context);
final nav = Navigator.of(context);
// validate password
if (_ctrNewPassword.text.length < 6) {
// password has to be at least 6 characters long
showSimpleSnackbar(scaffMgr,
text: 'Password has to be at least 6 characters longs',
action: 'Dismiss');
_ctrNewPasswordRepeat.clear();
return;
}
if (_ctrNewPassword.text != _ctrNewPasswordRepeat.text) {
// new passwords do not match
showSimpleSnackbar(scaffMgr,
text: 'New passwords do not match', action: 'Dismiss');
_ctrNewPasswordRepeat.clear();
return;
}
if (hashPassword(_ctrOldPassword.text) != user?.password) {
// current password wrong
showSimpleSnackbar(scaffMgr,
text: 'Old password is wrong', action: 'Dismiss');
_ctrOldPassword.clear();
return;
}
final password = hashPassword(_ctrNewPassword.text);
// send request
doNetworkRequest(scaffMgr,
needUser: false,
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();
});
},
child: const Text('Change password'),
)
],
);
}
}