99 lines
3.1 KiB
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}';
|
|
}
|
|
}
|
|
}
|