diff --git a/lib/features/authentication/data/repositories/auth_repository_impl.dart b/lib/features/authentication/data/repositories/auth_repository_impl.dart index c83ca2f..555d3d1 100644 --- a/lib/features/authentication/data/repositories/auth_repository_impl.dart +++ b/lib/features/authentication/data/repositories/auth_repository_impl.dart @@ -1,4 +1,5 @@ import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:logger/logger.dart'; import '../../domain/repositories/auth_repository.dart'; import '../../data/models/auth_user.dart'; import '../../../../core/errors/auth_exceptions.dart'; @@ -74,11 +75,16 @@ class AuthRepositoryImpl implements AuthRepository { @override Future resetPassword(String email) async { try { + Logger.d('Sending password reset email to: ${email.replaceAll(RegExp(r'(?<=.{2}).(?=.*@)'), '*')}'); + await _supabase.auth.resetPasswordForEmail( email, redirectTo: 'com.sage.app://reset-password', ); + + Logger.i('Password reset email sent successfully'); } catch (e) { + Logger.e('Failed to send password reset email', error: e); throw AuthExceptionFactory.fromSupabaseError(e); } } @@ -194,22 +200,38 @@ class AuthRepositoryImpl implements AuthRepository { final user = _supabase.auth.currentUser; if (user == null) { + Logger.w('No authenticated user found for password change'); throw const SessionExpiredException(); } + Logger.d('Verifying current password for user: ${user.email!.replaceAll(RegExp(r'(?<=.{2}).(?=.*@)'), '*')}'); + // First verify current password by attempting to sign in await _supabase.auth.signInWithPassword( email: user.email!, password: currentPassword, ); + // Validate new password strength + if (newPassword.length < 8) { + throw const WeakPasswordException( + message: 'Password must be at least 8 characters long', + code: 'PASSWORD_TOO_SHORT', + ); + } + + Logger.i('Current password verified, updating to new password'); + // If sign in succeeded, update password await _supabase.auth.updateUser( UserAttributes( password: newPassword, ), ); + + Logger.i('Password changed successfully'); } catch (e) { + Logger.e('Failed to change password', error: e); throw AuthExceptionFactory.fromSupabaseError(e); } } @@ -305,26 +327,41 @@ class AuthRepositoryImpl implements AuthRepository { @override Future updatePasswordFromReset(String newPassword) async { try { + Logger.d('Attempting to update password from reset token'); + // Extract the current session to verify we have a valid reset token final session = _supabase.auth.currentSession; if (session == null) { + Logger.w('No valid reset session found'); throw const InvalidTokenException( message: 'No valid password reset session found. Please request a new reset link.', code: 'NO_RESET_SESSION', ); } + // Validate password strength before sending to Supabase + if (newPassword.length < 8) { + throw const WeakPasswordException( + message: 'Password must be at least 8 characters long', + code: 'PASSWORD_TOO_SHORT', + ); + } + // Update password using Supabase updateUser + Logger.i('Updating user password'); await _supabase.auth.updateUser( UserAttributes( password: newPassword, ), ); + Logger.i('Password updated successfully, signing out'); + // After successful password update, sign out to force re-authentication await _supabase.auth.signOut(); } catch (e) { + Logger.e('Failed to update password from reset', error: e); throw AuthExceptionFactory.fromSupabaseError(e); } } diff --git a/pubspec.yaml b/pubspec.yaml index c1fbe10..6ece433 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,9 @@ dependencies: # Secure storage for authentication tokens flutter_secure_storage: ^9.0.0 + + # Logging for debugging and monitoring + logger: ^2.0.2 dev_dependencies: flutter_test: