218 lines
6.6 KiB
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';
|
|
}
|
|
}
|
|
}
|
|
|