Auth réparée

This commit is contained in:
PC-PAUL\paulf 2025-03-05 19:56:58 +01:00
parent 3c5d3b4c5a
commit d3813bfcdb
6 changed files with 136 additions and 177 deletions

View File

@ -4,7 +4,22 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": "Attach to Chrome",
"port": 9222,
"request": "attach",
"type": "chrome",
"webRoot": "${workspaceFolder}",
"preLaunchTask": "npm: vite",
},
{
"name": "Launch Chrome",
"request": "launch",
"type": "chrome",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
},
{ {
"name": "Launch Edge", "name": "Launch Edge",
"request": "launch", "request": "launch",

View File

@ -44,8 +44,8 @@ class MyApp extends StatelessWidget {
inputDecorationTheme: InputDecorationTheme( inputDecorationTheme: InputDecorationTheme(
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
// Bordure lorsqu'il est focus // Bordure lorsqu'il est focus
borderSide: borderSide: BorderSide(
BorderSide(color: AppColors.noir), // Couleur rouge quand focus color: AppColors.noir), // Couleur rouge quand focus
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
// Bordure par défaut (non focus) // Bordure par défaut (non focus)
@ -75,24 +75,6 @@ class MyApp extends StatelessWidget {
'/user_management': (context) => const UserManagementPage(), '/user_management': (context) => const UserManagementPage(),
}, },
// Conditionally set home based on authentication state // Conditionally set home based on authentication state
home: StreamBuilder<User?>( home: LoginPage());
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User? user = snapshot.data;
if (user == null) {
return const LoginPage(); // User not logged in, show LoginPage
}
return const CalendarPage(); // User logged in, show CalendarPage
}
// Checking auth state, show loading indicator
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
},
),
);
} }
} }

View File

@ -5,27 +5,38 @@ class UserProvider extends ChangeNotifier {
String? _firstName; String? _firstName;
String? _lastName; String? _lastName;
String? _role; String? _role;
String? _profilePictureUrl; // String? _profilePictureUrl;
String? _email; String? _email;
String? _phoneNumber; // String? _phoneNumber;
String? get uid => _uid; String? get uid => _uid;
String? get firstName => _firstName; String? get firstName => _firstName;
String? get lastName => _lastName; String? get lastName => _lastName;
String? get role => _role; String? get role => _role;
String? get profilePhotoUrl => _profilePictureUrl; // String? get profilePhotoUrl => _profilePictureUrl;
String? get email => _email; String? get email => _email;
String? get phoneNumber => _phoneNumber; // String? get phoneNumber => _phoneNumber;
// void setUserData(Map<String, dynamic> userData, String uid) {
// _uid = uid;
// _firstName = userData['firstName'];
// _lastName = userData['lastName'];
// _role = userData['role'] ?? 'USER'; // Default role if not provided
// // _profilePictureUrl = userData['profilePhotoUrl'];
// _email = userData['email'];
// // _phoneNumber = userData['phoneNumber'];
// notifyListeners(); // Notify listeners that state has changed
// }
void setUserData(Map<String, dynamic> userData, String uid) { void setUserData(Map<String, dynamic> userData, String uid) {
_uid = uid; _uid = uid;
_firstName = userData['firstName']; _firstName = userData['firstName'];
_lastName = userData['lastName']; _lastName = userData['lastName'];
_role = userData['role'] ?? 'USER'; // Default role if not provided _role = userData['role'] ?? 'USER'; // Default role if not provided
_profilePictureUrl = userData['profilePhotoUrl'];
_email = userData['email']; _email = userData['email'];
_phoneNumber = userData['phoneNumber'];
notifyListeners(); // Notify listeners that state has changed print("User data set: $_firstName $_lastName ($_email)");
notifyListeners();
} }
void clearUserData() { void clearUserData() {
@ -33,9 +44,9 @@ class UserProvider extends ChangeNotifier {
_firstName = null; _firstName = null;
_lastName = null; _lastName = null;
_role = null; _role = null;
_profilePictureUrl = null; // _profilePictureUrl = null;
_email = null; _email = null;
_phoneNumber = null; // _phoneNumber = null;
notifyListeners(); notifyListeners();
} }
} }

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:em2rp/views/widgets/nav/main_drawer.dart'; import 'package:em2rp/views/widgets/nav/main_drawer.dart';
import 'package:provider/provider.dart'; // Import Provider import 'package:provider/provider.dart'; // Import Provider
import 'package:em2rp/providers/user_provider.dart'; // Import UserProvider import 'package:em2rp/providers/user_provider.dart'; // Import UserProvider

View File

@ -1,6 +1,5 @@
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:em2rp/providers/user_provider.dart'; import 'package:em2rp/providers/user_provider.dart';
import 'package:em2rp/views/widgets/auth/forgot_password_dialog.dart';
import 'package:em2rp/views/widgets/auth/mail_textfield.dart'; import 'package:em2rp/views/widgets/auth/mail_textfield.dart';
import 'package:em2rp/views/widgets/error_message.dart'; import 'package:em2rp/views/widgets/error_message.dart';
import 'package:em2rp/views/widgets/auth/forgot_password_button.dart'; import 'package:em2rp/views/widgets/auth/forgot_password_button.dart';
@ -11,6 +10,7 @@ import 'package:em2rp/views/widgets/auth/password_textfield.dart';
import 'package:em2rp/views/widgets/auth/welcome_text.dart'; import 'package:em2rp/views/widgets/auth/welcome_text.dart';
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:em2rp/views/widgets/auth/forgot_password_dialog.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class LoginPage extends StatefulWidget { class LoginPage extends StatefulWidget {
@ -33,13 +33,11 @@ class _LoginPageState extends State<LoginPage> {
void dispose() { void dispose() {
_emailController.dispose(); _emailController.dispose();
_passwordController.dispose(); _passwordController.dispose();
print("LoginPage DISPOSED");
super.dispose(); super.dispose();
} }
Future<void> _loginUser() async { Future<void> _signInWithEmailAndPassword() async {
if (!mounted) return; // Early exit if widget is unmounted // Pas de vérification mounted ici, le widget reste monté pendant toute l'opération
setState(() { setState(() {
_errorMessage = ''; _errorMessage = '';
_isLoading = true; _isLoading = true;
@ -47,95 +45,54 @@ class _LoginPageState extends State<LoginPage> {
_highlightEmailField = false; _highlightEmailField = false;
}); });
String email = _emailController.text.trim();
String password = _passwordController.text;
try { try {
// 1. Sign in with Firebase Authentication final UserCredential userCredential =
UserCredential userCredential = await FirebaseAuth.instance await FirebaseAuth.instance.signInWithEmailAndPassword(
.signInWithEmailAndPassword(email: email, password: password); email: _emailController.text.trim(),
User? user = userCredential.user; password: _passwordController.text,
);
final uid = userCredential.user!.uid;
if (user != null) { final DocumentSnapshot userDoc =
// 2. Fetch user data from Firestore await FirebaseFirestore.instance.collection('users').doc(uid).get();
print(
"Fetching user data from Firestore..."); // Log before Firestore fetch
DocumentSnapshot userDoc = await FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.get();
print("Firestore DocumentSnapshot retrieved."); // Log after fetch
if (userDoc.exists) { if (userDoc.exists) {
print("Firestore Document Exists: true"); // Log doc exists check print("User document found: ${userDoc.data()}");
print("Document ID: ${userDoc.id}"); // Log document ID Provider.of<UserProvider>(context, listen: false)
print( .setUserData(userDoc.data() as Map<String, dynamic>, uid);
"Before data cast - userDoc.data(): ${userDoc.data()}"); // Log raw data before cast
Map<String, dynamic> userData = // Maintenant que toutes les données sont chargées, naviguer vers CalendarPage.
userDoc.data() as Map<String, dynamic>; Navigator.of(context).pushReplacementNamed('/calendar');
print(
"After data cast - userData: $userData"); // Log userData after cast
// 3. Store user data in UserProvider
final userProvider =
Provider.of<UserProvider>(context, listen: false);
print(
"Before setUserData call - userProvider: $userProvider"); // Log userProvider instance
userProvider.setUserData(
userData, user.uid); // Store user data in provider
print("After setUserData call"); // Log after setUserData is called
print(
'Login successful! Role: ${userProvider.role}'); // Log success and role
if (mounted) {
Navigator.of(context).pushReplacementNamed(
'/calendar'); // 4. Navigate to CalendarPage
}
} else { } else {
// User document not found in Firestore
print(
"Firestore Document Exists: false"); // Log doc exists check - false
if (mounted) {
setState(() { setState(() {
_errorMessage = "Aucune donnée utilisateur trouvée.";
_isLoading = false; _isLoading = false;
_errorMessage =
"Erreur: Utilisateur non trouvé dans la base de données.";
}); });
} }
print('Login Error: Firestore user document not found');
}
}
} on FirebaseAuthException catch (e) { } on FirebaseAuthException catch (e) {
// Firebase Authentication error
if (mounted) {
setState(() { setState(() {
_isLoading = false; _isLoading = false;
if (e.code == 'user-not-found' || e.code == 'wrong-password') { if (e.code == 'user-not-found' || e.code == 'wrong-password') {
_errorMessage = "Email ou mot de passe incorrect."; _errorMessage = "Email ou mot de passe incorrect.";
_highlightPasswordField = true; _highlightPasswordField = true;
_highlightEmailField = true; _highlightEmailField = true;
} else if (e.code == 'invalid-email') {
_errorMessage = "Adresse email invalide.";
_highlightEmailField = true;
} else { } else {
_errorMessage = "Erreur de connexion. Veuillez réessayer."; _errorMessage = "Erreur de connexion. Veuillez réessayer.";
} }
}); });
} } catch (e) {
print('Login Error (FirebaseAuth): ${e.code} - ${e.message}');
} finally {
if (mounted) {
setState(() { setState(() {
_errorMessage =
"Erreur lors de la récupération des données utilisateur.";
_isLoading = false; _isLoading = false;
}); });
} }
} }
}
void _togglePasswordVisibility() { void _togglePasswordVisibility() {
if (mounted) setState(() => _obscurePassword = !_obscurePassword); setState(() {
_obscurePassword = !_obscurePassword;
});
} }
void _forgotPassword() { void _forgotPassword() {
@ -151,9 +108,13 @@ class _LoginPageState extends State<LoginPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: LayoutBuilder( body: LayoutBuilder(
builder: (context, constraints) => constraints.maxWidth > 900 builder: (context, constraints) {
? _buildLargeScreenLayout(context) if (constraints.maxWidth > 900) {
: _buildSmallScreenLayout(context), return _buildLargeScreenLayout(context);
} else {
return _buildSmallScreenLayout(context);
}
},
), ),
); );
} }
@ -161,11 +122,15 @@ class _LoginPageState extends State<LoginPage> {
Widget _buildLargeScreenLayout(BuildContext context) { Widget _buildLargeScreenLayout(BuildContext context) {
return Row( return Row(
children: <Widget>[ children: <Widget>[
const Expanded(flex: 6, child: ImageSectionWidget()), Expanded(
flex: 6,
child: const ImageSectionWidget(), // Affiche l'image de gauche
),
Expanded( Expanded(
flex: 4, flex: 4,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 30), padding:
const EdgeInsets.symmetric(horizontal: 50.0, vertical: 30.0),
child: _buildLoginForm(context), child: _buildLoginForm(context),
), ),
), ),
@ -200,26 +165,13 @@ class _LoginPageState extends State<LoginPage> {
passwordController: _passwordController, passwordController: _passwordController,
obscurePassword: _obscurePassword, obscurePassword: _obscurePassword,
highlightPasswordField: _highlightPasswordField, highlightPasswordField: _highlightPasswordField,
onTogglePasswordVisibility: () { onTogglePasswordVisibility: _togglePasswordVisibility,
if (!mounted) return;
setState(() {
_obscurePassword = !_obscurePassword;
});
},
), ),
ForgotPasswordButtonWidget(onPressed: () { ForgotPasswordButtonWidget(onPressed: _forgotPassword),
showDialog(
context: context,
builder: (BuildContext context) {
return const ForgotPasswordDialogWidget();
},
);
}),
const SizedBox(height: 30), const SizedBox(height: 30),
LoginButtonWidget( LoginButtonWidget(
isLoading: _isLoading, isLoading: _isLoading,
onPressed: () => Navigator.of(context).pushNamed( onPressed: _signInWithEmailAndPassword,
'/calendar'), //Ici, remplacer par une fonction de connexion avec firebase Auth
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
ErrorMessageWidget(errorMessage: _errorMessage), ErrorMessageWidget(errorMessage: _errorMessage),

View File

@ -4,7 +4,7 @@ import 'package:em2rp/views/calendar_page.dart';
import 'package:em2rp/views/my_account_page.dart'; import 'package:em2rp/views/my_account_page.dart';
import 'package:em2rp/views/user_management_page.dart'; import 'package:em2rp/views/user_management_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; // Import Provider // Import Provider
class MainDrawer extends StatelessWidget { class MainDrawer extends StatelessWidget {
final String currentPage; final String currentPage;