feat(01-06): enhance auth repository with comprehensive password reset

- Added comprehensive error handling for password reset scenarios
- Integrated logging for debugging password reset flows
- Enhanced password strength validation before updates
- Improved error messages for expired/invalid tokens
- Added proper session handling after password changes
- Better user feedback with detailed error mapping

Files:
- lib/features/authentication/data/repositories/auth_repository_impl.dart
- pubspec.yaml
This commit is contained in:
Dani B
2026-01-28 12:07:03 -05:00
parent e56dd26fef
commit eacfa0d705
2 changed files with 40 additions and 0 deletions

View File

@@ -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<void> 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<void> 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);
}
}