186 lines
6.4 KiB
Dart
186 lines
6.4 KiB
Dart
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
|
import 'package:travel_mate/services/error_service.dart';
|
|
|
|
/// Service for handling Firebase authentication operations.
|
|
///
|
|
/// This service provides methods for user authentication including email/password
|
|
/// sign-in, Google sign-in, Apple sign-in, password reset, and account management.
|
|
/// It acts as a wrapper around Firebase Auth functionality.
|
|
class AuthService {
|
|
/// Error service for logging authentication errors.
|
|
final _errorService = ErrorService();
|
|
|
|
/// Firebase Auth instance for authentication operations.
|
|
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
|
|
|
|
/// Gets the currently authenticated user.
|
|
///
|
|
/// Returns null if no user is currently signed in.
|
|
User? get currentUser => firebaseAuth.currentUser;
|
|
|
|
/// Stream that emits authentication state changes.
|
|
///
|
|
/// Emits the current user when authenticated, null when not authenticated.
|
|
Stream<User?> get authStateChanges => firebaseAuth.authStateChanges();
|
|
|
|
/// Signs in a user with email and password.
|
|
///
|
|
/// Returns a [UserCredential] containing the authenticated user's information.
|
|
/// Throws [FirebaseAuthException] if authentication fails.
|
|
Future<UserCredential> signInWithEmailAndPassword({
|
|
required String email,
|
|
required String password,
|
|
}) async {
|
|
return await firebaseAuth.signInWithEmailAndPassword(
|
|
email: email,
|
|
password: password,
|
|
);
|
|
}
|
|
|
|
/// Creates a new user account with email and password.
|
|
///
|
|
/// Returns a [UserCredential] containing the new user's information.
|
|
/// Throws [FirebaseAuthException] if account creation fails.
|
|
Future<UserCredential> signUpWithEmailAndPassword({
|
|
required String email,
|
|
required String password,
|
|
}) async {
|
|
return await firebaseAuth.createUserWithEmailAndPassword(
|
|
email: email,
|
|
password: password,
|
|
);
|
|
}
|
|
|
|
/// Signs out the current user.
|
|
///
|
|
/// Clears the authentication state and signs out the user from Firebase.
|
|
Future<void> signOut() async {
|
|
await firebaseAuth.signOut();
|
|
}
|
|
|
|
/// Sends a password reset email to the specified email address.
|
|
///
|
|
/// The user will receive an email with instructions to reset their password.
|
|
/// Throws [FirebaseAuthException] if the email is invalid or other errors occur.
|
|
Future<void> resetPassword(String email) async {
|
|
await firebaseAuth.sendPasswordResetEmail(email: email);
|
|
}
|
|
|
|
/// Updates the display name of the current user.
|
|
///
|
|
/// Requires a user to be currently authenticated.
|
|
/// Throws if no user is signed in.
|
|
Future<void> updateDisplayName({required String displayName}) async {
|
|
await currentUser!.updateDisplayName(displayName);
|
|
}
|
|
|
|
/// Deletes the current user's account permanently.
|
|
///
|
|
/// Requires re-authentication with the user's current password for security.
|
|
/// This operation cannot be undone.
|
|
///
|
|
/// [password] - The user's current password for re-authentication
|
|
/// [email] - The user's email address for re-authentication
|
|
Future<void> deleteAccount({
|
|
required String password,
|
|
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 firebaseAuth.signOut();
|
|
}
|
|
|
|
/// Resets the user's password after re-authentication.
|
|
///
|
|
/// This method allows users to change their password by providing their
|
|
/// current password for security verification.
|
|
///
|
|
/// [currentPassword] - The user's current password for verification
|
|
/// [newPassword] - The new password to set
|
|
/// [email] - The user's email address for re-authentication
|
|
Future<void> resetPasswordFromCurrentPassword({
|
|
required String currentPassword,
|
|
required String newPassword,
|
|
required String email,
|
|
}) async {
|
|
// Re-authenticate the user for security
|
|
AuthCredential credential = EmailAuthProvider.credential(
|
|
email: email,
|
|
password: currentPassword,
|
|
);
|
|
await currentUser!.reauthenticateWithCredential(credential);
|
|
|
|
// Update to the new password
|
|
await currentUser!.updatePassword(newPassword);
|
|
}
|
|
|
|
/// Ensures Google Sign-In is properly initialized.
|
|
///
|
|
/// This method must be called before attempting Google authentication.
|
|
Future<void> ensureInitialized() {
|
|
return GoogleSignInPlatform.instance.init(const InitParameters());
|
|
}
|
|
|
|
/// Signs in a user using Google authentication.
|
|
///
|
|
/// Handles the complete Google Sign-In flow including platform initialization
|
|
/// and credential exchange with Firebase.
|
|
///
|
|
/// Returns a [UserCredential] containing the authenticated user's information.
|
|
/// Throws various exceptions if authentication fails.
|
|
Future<UserCredential> signInWithGoogle() async {
|
|
try {
|
|
await ensureInitialized();
|
|
final AuthenticationResults result = await GoogleSignInPlatform.instance
|
|
.authenticate(const AuthenticateParameters());
|
|
final String? idToken = result.authenticationTokens.idToken;
|
|
if (idToken == null) {
|
|
throw FirebaseAuthException(
|
|
code: 'ERROR_MISSING_GOOGLE_ID_TOKEN',
|
|
message: 'Missing Google ID Token',
|
|
);
|
|
} else {
|
|
final OAuthCredential credential = GoogleAuthProvider.credential(
|
|
idToken: idToken,
|
|
);
|
|
UserCredential userCredential = await firebaseAuth.signInWithCredential(
|
|
credential,
|
|
);
|
|
|
|
// Return the UserCredential instead of void
|
|
return userCredential;
|
|
}
|
|
} on GoogleSignInException catch (e) {
|
|
_errorService.logError('Google Sign-In error: $e', StackTrace.current);
|
|
rethrow;
|
|
} on FirebaseAuthException catch (e) {
|
|
_errorService.logError(
|
|
'Firebase error during Google Sign-In initialization: $e',
|
|
StackTrace.current,
|
|
);
|
|
rethrow;
|
|
} catch (e) {
|
|
_errorService.logError(
|
|
'Unknown error during Google Sign-In initialization: $e',
|
|
StackTrace.current,
|
|
);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Signs in a user using Apple authentication.
|
|
///
|
|
/// This method is currently a placeholder for future Apple authentication support.
|
|
Future signInWithApple() async {
|
|
// TODO: Implement Apple sign-in
|
|
}
|
|
}
|