TIF_E41221079/lib/core/service/auth_service.dart

99 lines
3.1 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseMessaging _messaging = FirebaseMessaging.instance;
final _storage = const FlutterSecureStorage(
aOptions: AndroidOptions(
encryptedSharedPreferences: true,
resetOnError: true,
),
);
Future<void> login({required String email, required String password}) async {
try {
final cleanEmail = email.trim();
UserCredential userCredential = await _auth.signInWithEmailAndPassword(
email: cleanEmail,
password: password,
);
User? user = userCredential.user;
if (user == null) throw 'Login gagal, pengguna tidak ditemukan.';
DocumentSnapshot userDoc =
await _firestore.collection('siswa').doc(user.uid).get();
if (!userDoc.exists) {
await _auth.signOut();
throw 'Data pengguna tidak ditemukan di database.';
}
Map<String, dynamic> data = userDoc.data() as Map<String, dynamic>;
String role = data['role'] ?? 'unknown';
if (role != 'Orang Tua') {
await _auth.signOut();
throw 'Akses ditolak. Akun ini bukan akun Orang Tua.';
}
// 1. Ambil FCM Token perangkat baru ini
String? fcmToken = await _messaging.getToken();
// 2. Update Token ke Firestore sebagai token aktif tunggal
await _firestore.collection('siswa').doc(user.uid).set({
'fcm_token': fcmToken,
'last_login': FieldValue.serverTimestamp(),
}, SetOptions(merge: true));
String? idToken = await user.getIdToken();
// 3. Simpan Session & Token FCM ke Lokal
await _storage.write(key: 'access_token', value: idToken);
await _storage.write(key: 'uid', value: user.uid);
await _storage.write(key: 'role', value: role);
if (fcmToken != null) {
await _storage.write(
key: 'fcm_token',
value: fcmToken,
); // Simpan untuk validasi nanti
}
} on FirebaseAuthException catch (e) {
throw _handleFirebaseAuthError(e);
} catch (e) {
rethrow;
}
}
Future<void> logout() async {
await _auth.signOut();
await _storage.deleteAll();
}
Future<String?> getAccessToken() async =>
await _storage.read(key: 'access_token');
// Helper untuk mengambil token FCM yang tersimpan di HP ini
Future<String?> getStoredFcmToken() async =>
await _storage.read(key: 'fcm_token');
String _handleFirebaseAuthError(FirebaseAuthException e) {
switch (e.code) {
case 'invalid-credential':
return 'Email atau kata sandi salah.';
case 'user-not-found':
return 'Email tidak terdaftar.';
case 'too-many-requests':
return 'Terlalu banyak percobaan. Silakan coba lagi nanti.';
default:
return 'Terjadi kesalahan: ${e.message}';
}
}
}