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,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|