Encrypted messaging app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
5.7 KiB

import 'dart:convert';
import 'dart:typed_data';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:pointycastle/impl.dart';
import '/components/flash_message.dart';
import '/components/custom_title_bar.dart';
import '/models/my_profile.dart';
import '/utils/encryption/aes_helper.dart';
import '/utils/encryption/crypto_utils.dart';
import '/utils/storage/session_cookie.dart';
@immutable
class ChangePassword extends StatelessWidget {
ChangePassword({
Key? key,
required this.privateKey
}) : super(key: key);
final RSAPrivateKey privateKey;
final _formKey = GlobalKey<FormState>();
final TextEditingController _currentPasswordController = TextEditingController();
final TextEditingController _newPasswordController = TextEditingController();
final TextEditingController _newPasswordConfirmController = TextEditingController();
bool invalidCurrentPassword = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CustomTitleBar(
title: Text(
'Profile',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold
)
),
showBack: true,
backgroundColor: Colors.transparent,
),
body: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.only(
left: 20,
right: 20,
top: 30,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'Change Password',
style: TextStyle(
fontSize: 25,
),
),
const SizedBox(height: 30),
TextFormField(
controller: _currentPasswordController,
decoration: const InputDecoration(
hintText: 'Current Password',
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Enter your current password';
}
if (invalidCurrentPassword) {
return 'Invalid password';
}
return null;
},
),
const SizedBox(height: 10),
TextFormField(
controller: _newPasswordController,
obscureText: true,
enableSuggestions: false,
autocorrect: false,
decoration: const InputDecoration(
hintText: 'New Password',
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Enter a new password';
}
return null;
},
),
const SizedBox(height: 10),
TextFormField(
controller: _newPasswordConfirmController,
obscureText: true,
enableSuggestions: false,
autocorrect: false,
decoration: const InputDecoration(
hintText: 'Confirm Password',
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Confirm your password';
}
if (value != _newPasswordController.text) {
return 'Passwords do not match';
}
return null;
},
),
const SizedBox(height: 15),
ElevatedButton(
onPressed: () {
if (!_formKey.currentState!.validate()) {
return;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
_changePassword(context)
.then((dynamic) {
Navigator.of(context).pop();
});
},
child: const Text('Submit'),
),
],
)
)
)
);
}
Future<void> _changePassword(BuildContext context) async {
String privateKeyPem = CryptoUtils.encodeRSAPrivateKeyToPem(privateKey);
String privateKeyEncrypted = AesHelper.aesEncrypt(
_newPasswordController.text,
Uint8List.fromList(privateKeyPem.codeUnits),
);
String payload = jsonEncode({
'old_password': _currentPasswordController.text,
'new_password': _newPasswordController.text,
'new_password_confirm': _newPasswordConfirmController.text,
'private_key': privateKeyEncrypted,
});
var resp = await http.post(
await MyProfile.getServerUrl('api/v1/auth/change_password'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'cookie': await getSessionCookie(),
},
body: payload,
);
if (resp.statusCode == 403) {
invalidCurrentPassword = true;
_formKey.currentState!.validate();
return;
}
if (resp.statusCode != 204) {
showMessage(
'An unexpected error occured, please try again later.',
context,
);
}
}
}