feat: refactor account deletion to handle requires-recent-login and update Android package ID.
This commit is contained in:
@@ -15,7 +15,7 @@ if (keystorePropertiesFile.exists()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "be.davdayronvl.travel_mate"
|
namespace = "be.devdayronvl.travel_mate"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId = "be.davdayronvl.travel_mate"
|
applicationId = "be.devdayronvl.travel_mate"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
|
|||||||
@@ -7,17 +7,69 @@
|
|||||||
"client": [
|
"client": [
|
||||||
{
|
{
|
||||||
"client_info": {
|
"client_info": {
|
||||||
"mobilesdk_app_id": "1:521527250907:android:be3db7fc84f053ec7da1fe",
|
"mobilesdk_app_id": "1:521527250907:android:56c632e98c7826347da1fe",
|
||||||
"android_client_info": {
|
"android_client_info": {
|
||||||
"package_name": "be.davdayronvl.travel_mate"
|
"package_name": "be.devdayronvl.travel_mate"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oauth_client": [
|
"oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "521527250907-j0kt1hc8hc7qc2kedp4akehau754cn5d.apps.googleusercontent.com",
|
||||||
|
"client_type": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyAON_ol0Jr34tKbETvdDK9JCQdKNawxBeQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "521527250907-j0kt1hc8hc7qc2kedp4akehau754cn5d.apps.googleusercontent.com",
|
||||||
|
"client_type": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_id": "521527250907-196i04qgm4talrosgi0ne0q8en90hkkh.apps.googleusercontent.com",
|
||||||
|
"client_type": 2,
|
||||||
|
"ios_info": {
|
||||||
|
"bundle_id": "be.devdayronvl.TravelMate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:521527250907:android:be3db7fc84f053ec7da1fe",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.example.travel_mate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "521527250907-19lrclc10eb0p8li1qutepctfqdohn0b.apps.googleusercontent.com",
|
||||||
|
"client_type": 1,
|
||||||
|
"android_info": {
|
||||||
|
"package_name": "com.example.travel_mate",
|
||||||
|
"certificate_hash": "2374761dc92a30812608c072638510002041eca8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_id": "521527250907-5v8l011nod30a6c52nkmk69d00h0ma0q.apps.googleusercontent.com",
|
||||||
|
"client_type": 1,
|
||||||
|
"android_info": {
|
||||||
|
"package_name": "com.example.travel_mate",
|
||||||
|
"certificate_hash": "c98141ab89d42b16c273e611054e7c87aa773d83"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"client_id": "521527250907-lqgj1lmfcsjusm2be9r6kpuanq3jvjcd.apps.googleusercontent.com",
|
"client_id": "521527250907-lqgj1lmfcsjusm2be9r6kpuanq3jvjcd.apps.googleusercontent.com",
|
||||||
"client_type": 1,
|
"client_type": 1,
|
||||||
"android_info": {
|
"android_info": {
|
||||||
"package_name": "be.davdayronvl.travel_mate",
|
"package_name": "com.example.travel_mate",
|
||||||
"certificate_hash": "9b7e3f14f0fcae0034ed977b5d40305b1812308d"
|
"certificate_hash": "9b7e3f14f0fcae0034ed977b5d40305b1812308d"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -39,10 +91,10 @@
|
|||||||
"client_type": 3
|
"client_type": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"client_id": "521527250907-3i1qe2656eojs8k9hjdi573j09i9p41m.apps.googleusercontent.com",
|
"client_id": "521527250907-196i04qgm4talrosgi0ne0q8en90hkkh.apps.googleusercontent.com",
|
||||||
"client_type": 2,
|
"client_type": 2,
|
||||||
"ios_info": {
|
"ios_info": {
|
||||||
"bundle_id": "com.example.travelMate"
|
"bundle_id": "be.devdayronvl.TravelMate"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.travel_mate
|
package be.devdayronvl.travel_mate
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:travel_mate/components/widgets/user_state_widget.dart';
|
import 'package:travel_mate/components/widgets/user_state_widget.dart';
|
||||||
import 'package:travel_mate/services/error_service.dart';
|
import 'package:travel_mate/services/error_service.dart';
|
||||||
@@ -789,7 +790,7 @@ class ProfileContent extends StatelessWidget {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
user_state.UserModel user,
|
user_state.UserModel user,
|
||||||
) {
|
) {
|
||||||
final passwordController = TextEditingController();
|
final confirmationController = TextEditingController();
|
||||||
final authService = AuthService();
|
final authService = AuthService();
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
@@ -801,15 +802,15 @@ class ProfileContent extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible.',
|
'Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible.\n\nPour confirmer, veuillez écrire "CONFIRMER" ci-dessous.',
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
TextField(
|
TextField(
|
||||||
controller: passwordController,
|
controller: confirmationController,
|
||||||
obscureText: true,
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Confirmez votre mot de passe',
|
labelText: 'Écrivez CONFIRMER',
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
|
hintText: 'CONFIRMER',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -821,11 +822,18 @@ class ProfileContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
try {
|
if (confirmationController.text != 'CONFIRMER') {
|
||||||
await authService.deleteAccount(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
password: passwordController.text,
|
SnackBar(
|
||||||
email: user.email,
|
content: Text('Veuillez écrire CONFIRMER pour valider'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await authService.deleteAccount();
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
@@ -836,11 +844,34 @@ class ProfileContent extends StatelessWidget {
|
|||||||
(route) => false,
|
(route) => false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} on FirebaseAuthException catch (e) {
|
||||||
_errorService.showError(
|
if (e.code == 'requires-recent-login') {
|
||||||
message: 'Erreur: Mot de passe incorrect',
|
if (context.mounted) {
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Par sécurité, veuillez vous reconnecter avant de supprimer votre compte',
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
duration: Duration(seconds: 4),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (context.mounted) {
|
||||||
|
_errorService.showError(
|
||||||
|
message: 'Erreur lors de la suppression: ${e.message}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (context.mounted) {
|
||||||
|
_errorService.showError(
|
||||||
|
message: 'Erreur inattendue: ${e.toString()}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||||
child: Text('Supprimer'),
|
child: Text('Supprimer'),
|
||||||
|
|||||||
@@ -1,8 +1,45 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import '../blocs/auth/auth_bloc.dart';
|
||||||
|
import '../blocs/auth/auth_event.dart';
|
||||||
|
import '../blocs/auth/auth_state.dart';
|
||||||
|
|
||||||
class ForgotPasswordPage extends StatelessWidget {
|
class ForgotPasswordPage extends StatefulWidget {
|
||||||
const ForgotPasswordPage({super.key});
|
const ForgotPasswordPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ForgotPasswordPage> createState() => _ForgotPasswordPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||||
|
final _emailController = TextEditingController();
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_emailController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _validateEmail(String? value) {
|
||||||
|
if (value == null || value.trim().isEmpty) {
|
||||||
|
return 'Email requis';
|
||||||
|
}
|
||||||
|
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
|
||||||
|
if (!emailRegex.hasMatch(value.trim())) {
|
||||||
|
return 'Email invalide';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _submit() {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
context.read<AuthBloc>().add(
|
||||||
|
AuthPasswordResetRequested(email: _emailController.text.trim()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -16,15 +53,40 @@ class ForgotPasswordPage extends StatelessWidget {
|
|||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: BlocListener<AuthBloc, AuthState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state is AuthPasswordResetSent) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Email de réinitialisation envoyé !'),
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else if (state is AuthError) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(state.message),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
"Travel Mate",
|
"Travel Mate",
|
||||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
@@ -32,7 +94,10 @@ class ForgotPasswordPage extends StatelessWidget {
|
|||||||
const Text(
|
const Text(
|
||||||
"Vous avez oublié votre mot de passe ? \n Ne vous inquiétez pas vous pouvez le réinitaliser !",
|
"Vous avez oublié votre mot de passe ? \n Ne vous inquiétez pas vous pouvez le réinitaliser !",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
@@ -40,33 +105,71 @@ class ForgotPasswordPage extends StatelessWidget {
|
|||||||
const Text(
|
const Text(
|
||||||
"Quel est votre email ? \n Si celui-ci existe dans note base de donées, nous vous enverrons un mail avec un mot de passe unique.",
|
"Quel est votre email ? \n Si celui-ci existe dans note base de donées, nous vous enverrons un mail avec un mot de passe unique.",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
const TextField(
|
TextFormField(
|
||||||
decoration: InputDecoration(
|
controller: _emailController,
|
||||||
labelText: 'example@travelmate.com',
|
validator: _validateEmail,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Email',
|
||||||
|
hintText: 'example@travelmate.com',
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
),
|
),
|
||||||
|
prefixIcon: Icon(Icons.email_outlined),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
|
|
||||||
ElevatedButton(
|
BlocBuilder<AuthBloc, AuthState>(
|
||||||
onPressed: () {
|
builder: (context, state) {
|
||||||
// Logique de connexion
|
final isLoading = state is AuthLoading;
|
||||||
},
|
|
||||||
|
return ElevatedButton(
|
||||||
|
onPressed: isLoading ? null : _submit,
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
minimumSize: const Size.fromHeight(50),
|
minimumSize: const Size.fromHeight(50),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).brightness ==
|
||||||
|
Brightness.dark
|
||||||
|
? Colors.white
|
||||||
|
: Colors.black,
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context).brightness ==
|
||||||
|
Brightness.dark
|
||||||
|
? Colors.black
|
||||||
|
: Colors.white,
|
||||||
),
|
),
|
||||||
child: const Text('Envoyer', style: TextStyle(fontSize: 18)),
|
child: isLoading
|
||||||
|
? SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
color:
|
||||||
|
Theme.of(context).brightness ==
|
||||||
|
Brightness.dark
|
||||||
|
? Colors.black
|
||||||
|
: Colors.white,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const Text(
|
||||||
|
'Envoyer',
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
@@ -84,7 +187,10 @@ class ForgotPasswordPage extends StatelessWidget {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// Go to sign up page
|
// Go to sign up page
|
||||||
Navigator.pushNamed(context, '/signup');
|
Navigator.pushReplacementNamed(
|
||||||
|
context,
|
||||||
|
'/signup',
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Inscrivez-vous !',
|
'Inscrivez-vous !',
|
||||||
@@ -101,6 +207,9 @@ class ForgotPasswordPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,11 +122,16 @@ class AuthRepository {
|
|||||||
String firstname,
|
String firstname,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
final firebaseUser = await _authService.signInWithGoogle();
|
firebase_auth.User? firebaseUser = _authService.currentUser;
|
||||||
|
|
||||||
if (firebaseUser.user != null) {
|
if (firebaseUser == null) {
|
||||||
|
final userCredential = await _authService.signInWithGoogle();
|
||||||
|
firebaseUser = userCredential.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firebaseUser != null) {
|
||||||
// Check if user already exists in Firestore
|
// Check if user already exists in Firestore
|
||||||
final existingUser = await getUserFromFirestore(firebaseUser.user!.uid);
|
final existingUser = await getUserFromFirestore(firebaseUser.uid);
|
||||||
|
|
||||||
if (existingUser != null) {
|
if (existingUser != null) {
|
||||||
return existingUser;
|
return existingUser;
|
||||||
@@ -134,12 +139,12 @@ class AuthRepository {
|
|||||||
|
|
||||||
// Create new user document for first-time Google sign-in
|
// Create new user document for first-time Google sign-in
|
||||||
final user = User(
|
final user = User(
|
||||||
id: firebaseUser.user!.uid,
|
id: firebaseUser.uid,
|
||||||
email: firebaseUser.user!.email ?? '',
|
email: firebaseUser.email ?? '',
|
||||||
nom: name,
|
nom: name,
|
||||||
prenom: firstname,
|
prenom: firstname,
|
||||||
phoneNumber: phoneNumber,
|
phoneNumber: phoneNumber,
|
||||||
profilePictureUrl: firebaseUser.user!.photoURL ?? 'Unknown',
|
profilePictureUrl: firebaseUser.photoURL ?? 'Unknown',
|
||||||
platform: 'google',
|
platform: 'google',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -181,22 +186,27 @@ class AuthRepository {
|
|||||||
String firstname,
|
String firstname,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
final firebaseUser = await _authService.signInWithApple();
|
firebase_auth.User? firebaseUser = _authService.currentUser;
|
||||||
|
|
||||||
if (firebaseUser.user != null) {
|
if (firebaseUser == null) {
|
||||||
final existingUser = await getUserFromFirestore(firebaseUser.user!.uid);
|
final userCredential = await _authService.signInWithApple();
|
||||||
|
firebaseUser = userCredential.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firebaseUser != null) {
|
||||||
|
final existingUser = await getUserFromFirestore(firebaseUser.uid);
|
||||||
|
|
||||||
if (existingUser != null) {
|
if (existingUser != null) {
|
||||||
return existingUser;
|
return existingUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
final user = User(
|
final user = User(
|
||||||
id: firebaseUser.user!.uid,
|
id: firebaseUser.uid,
|
||||||
email: firebaseUser.user!.email ?? '',
|
email: firebaseUser.email ?? '',
|
||||||
nom: name,
|
nom: name,
|
||||||
prenom: firstname,
|
prenom: firstname,
|
||||||
phoneNumber: phoneNumber,
|
phoneNumber: phoneNumber,
|
||||||
profilePictureUrl: firebaseUser.user!.photoURL ?? 'Unknown',
|
profilePictureUrl: firebaseUser.photoURL ?? 'Unknown',
|
||||||
platform: 'apple',
|
platform: 'apple',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -83,20 +83,30 @@ class AuthService {
|
|||||||
///
|
///
|
||||||
/// [password] - The user's current password for re-authentication
|
/// [password] - The user's current password for re-authentication
|
||||||
/// [email] - The user's email address for re-authentication
|
/// [email] - The user's email address for re-authentication
|
||||||
Future<void> deleteAccount({
|
Future<void> deleteAccount() async {
|
||||||
required String password,
|
try {
|
||||||
required String email,
|
|
||||||
}) async {
|
|
||||||
// Re-authenticate the user for security
|
|
||||||
AuthCredential credential = EmailAuthProvider.credential(
|
|
||||||
email: email,
|
|
||||||
password: password,
|
|
||||||
);
|
|
||||||
await currentUser!.reauthenticateWithCredential(credential);
|
|
||||||
|
|
||||||
// Delete the user account permanently
|
|
||||||
await currentUser!.delete();
|
await currentUser!.delete();
|
||||||
await firebaseAuth.signOut();
|
await firebaseAuth.signOut();
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
if (e.code == 'requires-recent-login') {
|
||||||
|
_errorService.logError(
|
||||||
|
'Delete account requires recent login',
|
||||||
|
StackTrace.current,
|
||||||
|
);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
_errorService.logError(
|
||||||
|
'Error deleting account: ${e.code} - ${e.message}',
|
||||||
|
StackTrace.current,
|
||||||
|
);
|
||||||
|
rethrow;
|
||||||
|
} catch (e) {
|
||||||
|
_errorService.logError(
|
||||||
|
'Unknown error deleting account: $e',
|
||||||
|
StackTrace.current,
|
||||||
|
);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets the user's password after re-authentication.
|
/// Resets the user's password after re-authentication.
|
||||||
|
|||||||
Reference in New Issue
Block a user