HydroNutrify_Ari_e41221567/lib/data/services/auth_service.dart

218 lines
6.6 KiB
Dart

import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:mobile_monitoring/data/models/service_result.dart';
/// Service untuk autentikasi (login, register, logout, reset password)
/// Backend logic - tidak ada dependency ke UI
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
User? get currentUser => _auth.currentUser;
Stream<User?> get authStateChanges => _auth.authStateChanges();
/// Login dengan email dan password
/// Returns ServiceResult dengan status success/failure dan pesan
Future<ServiceResult<User?>> signInWithEmailAndPassword({
required String email,
required String password,
}) async {
try {
debugPrint('[AuthService] Login attempt for: $email');
// Set language untuk error messages
_auth.setLanguageCode('id');
// Timeout untuk mencegah hang
final userCredential = await _auth
.signInWithEmailAndPassword(email: email, password: password)
.timeout(
const Duration(seconds: 20),
onTimeout: () {
throw TimeoutException('Login timeout');
},
);
debugPrint('[AuthService] ✓ Login success - User: ${userCredential.user?.email}');
return ServiceResult.success(
message: 'Login berhasil',
data: userCredential.user,
);
} on TimeoutException {
debugPrint('[AuthService] ✗ Login timeout');
return ServiceResult.failure(
message: 'Login timeout. Periksa koneksi atau Google Play Services.',
errorCode: 'timeout',
);
} on FirebaseAuthException catch (e) {
debugPrint('[AuthService] ✗ FirebaseAuthException: ${e.code} - ${e.message}');
final message = _mapFirebaseAuthError(e.code);
return ServiceResult.failure(
message: message,
errorCode: e.code,
);
} catch (e) {
debugPrint('[AuthService] ✗ Unexpected error: $e');
return ServiceResult.failure(
message: 'Terjadi kesalahan saat login',
errorCode: 'unknown',
);
}
}
/// Register akun baru dengan email, password, dan nama
Future<ServiceResult<User?>> registerWithEmailAndPassword({
required String email,
required String password,
required String name,
}) async {
try {
debugPrint('[AuthService] Register attempt for: $email');
final userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// Update display name
await userCredential.user?.updateDisplayName(name);
await userCredential.user?.reload();
debugPrint('[AuthService] ✓ Register success - User: ${userCredential.user?.email}');
return ServiceResult.success(
message: 'Registrasi berhasil',
data: userCredential.user,
);
} on FirebaseAuthException catch (e) {
debugPrint('[AuthService] ✗ Register FirebaseAuthException: ${e.code} - ${e.message}');
String message;
switch (e.code) {
case 'weak-password':
message = 'Password terlalu lemah';
break;
case 'email-already-in-use':
message = 'Email sudah terdaftar';
break;
case 'invalid-email':
message = 'Email tidak valid';
break;
default:
message = 'Terjadi kesalahan: ${e.message}';
}
return ServiceResult.failure(
message: message,
errorCode: e.code,
);
} catch (e) {
debugPrint('[AuthService] ✗ Register unexpected error: $e');
return ServiceResult.failure(
message: 'Terjadi kesalahan saat registrasi',
errorCode: 'unknown',
);
}
}
/// Logout user dari aplikasi
Future<ServiceResult<void>> signOut() async {
try {
debugPrint('[AuthService] Logout attempt');
await _auth.signOut();
debugPrint('[AuthService] ✓ Logout success');
return ServiceResult.success(message: 'Logout berhasil');
} catch (e) {
debugPrint('[AuthService] ✗ Logout error: $e');
return ServiceResult.failure(
message: 'Gagal logout',
errorCode: 'unknown',
);
}
}
/// Kirim email reset password
Future<ServiceResult<void>> resetPassword(String email) async {
try {
debugPrint('[AuthService] Reset password for: $email');
await _auth.sendPasswordResetEmail(email: email);
debugPrint('[AuthService] ✓ Reset password email sent');
return ServiceResult.success(
message: 'Link reset password telah dikirim ke email Anda',
);
} on FirebaseAuthException catch (e) {
debugPrint('[AuthService] ✗ Reset password FirebaseAuthException: ${e.code}');
String message;
switch (e.code) {
case 'user-not-found':
message = 'Email tidak terdaftar';
break;
case 'invalid-email':
message = 'Email tidak valid';
break;
default:
message = 'Terjadi kesalahan: ${e.message}';
}
return ServiceResult.failure(
message: message,
errorCode: e.code,
);
} catch (e) {
debugPrint('[AuthService] ✗ Reset password unexpected error: $e');
return ServiceResult.failure(
message: 'Terjadi kesalahan',
errorCode: 'unknown',
);
}
}
/// Validasi email format
bool isValidEmail(String email) {
return email.isNotEmpty && email.contains('@');
}
/// Validasi password
bool isValidPassword(String password) {
return password.length >= 6;
}
/// Map Firebase Auth error codes ke pesan yang user-friendly
String _mapFirebaseAuthError(String code) {
switch (code) {
case 'invalid-credential':
case 'wrong-password':
return 'Email atau password salah';
case 'user-not-found':
return 'Akun belum terdaftar';
case 'user-disabled':
return 'Akun dinonaktifkan';
case 'too-many-requests':
return 'Terlalu banyak percobaan, coba lagi nanti';
case 'network-request-failed':
return 'Koneksi internet bermasalah';
case 'operation-not-allowed':
return 'Email/Password belum diaktifkan di Firebase';
case 'app-not-authorized':
return 'App belum terdaftar di Firebase (package name/sha-1)';
case 'invalid-api-key':
return 'API key Firebase tidak valid';
case 'invalid-email':
return 'Format email tidak valid';
default:
return 'Login gagal: $code';
}
}
}