TKK_E32230206/lib/services/supabase_auth_service.dart

155 lines
4.9 KiB
Dart

import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/user_model.dart';
import '../core/api_config.dart';
import 'auth_service.dart';
/// Implementasi AuthService menggunakan Supabase
class SupabaseAuthService implements AuthService {
final supabase.SupabaseClient _client = supabase.Supabase.instance.client;
final Dio _dio = Dio();
@override
Future<UserModel> login(String email, String password) async {
try {
final response = await _client.auth.signInWithPassword(
email: email,
password: password,
);
final user = response.user;
if (user == null) {
throw Exception('Login gagal: User tidak ditemukan');
}
// Ambil device_id dari backend
String? deviceId;
try {
final deviceRes = await _dio.get('${ApiConfig.baseUrl}/device/my-device/${user.id}');
if (deviceRes.statusCode == 200) {
deviceId = deviceRes.data['device_id'];
}
} catch (e) {
print('Gagal mengambil info device: $e');
// Tidak melempar error agar login tetap sukses meskipun belum ada device
}
// Simpan device_id ke cache lokal agar auto-login selanjutnya super cepat
if (deviceId != null) {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('cached_device_id', deviceId);
}
return UserModel(
id: user.id,
name: user.userMetadata?['name'] ?? user.email?.split('@').first ?? 'User',
email: user.email ?? email,
token: response.session?.accessToken ?? '',
deviceId: deviceId,
);
} on supabase.AuthException catch (e) {
if (e.message.contains('Invalid login credentials')) {
throw Exception('Email atau password salah.');
} else if (e.message.contains('Email not confirmed')) {
throw Exception('Email belum diverifikasi.');
}
throw Exception(e.message);
} catch (e) {
throw Exception('Terjadi kesalahan koneksi atau server.');
}
}
@override
Future<UserModel> register(String name, String email, String password, String claimCode) async {
try {
final response = await _client.auth.signUp(
email: email,
password: password,
data: {'name': name},
);
final user = response.user;
if (user == null) {
throw Exception('Registrasi gagal');
}
// Klaim device setelah berhasil mendaftar ke Supabase
String? deviceId;
try {
final claimRes = await _dio.post('${ApiConfig.baseUrl}/device/claim', data: {
'claim_code': claimCode,
'user_id': user.id,
});
if (claimRes.statusCode == 200) {
deviceId = claimRes.data['device']['device_id'];
// Simpan device_id ke cache lokal
final prefs = await SharedPreferences.getInstance();
await prefs.setString('cached_device_id', deviceId!);
}
} catch (e) {
// Jika gagal klaim
String errorMsg = 'Gagal klaim perangkat.';
if (e is DioException && e.response?.data != null) {
errorMsg = e.response?.data['message'] ?? errorMsg;
}
throw Exception('Akun terbuat, tapi $errorMsg');
}
return UserModel(
id: user.id,
name: name,
email: email,
token: response.session?.accessToken ?? '',
deviceId: deviceId,
);
} on supabase.AuthException catch (e) {
if (e.message.contains('already registered')) {
throw Exception('Email sudah terdaftar.');
} else if (e.message.contains('weak')) {
throw Exception('Password terlalu lemah.');
}
throw Exception(e.message);
} catch (e) {
throw Exception('Terjadi kesalahan koneksi atau server.');
}
}
@override
Future<void> logout() async {
// Hapus sesi Supabase
await _client.auth.signOut();
// Hapus cache device_id agar tidak terbawa jika user login pakai akun lain
final prefs = await SharedPreferences.getInstance();
await prefs.remove('cached_device_id');
}
// Fungsi tambahan untuk memulihkan sesi
Future<UserModel?> checkSession() async {
final session = _client.auth.currentSession;
if (session != null) {
final user = session.user;
// Ambil device_id langsung dari cache lokal (cepat & offline-safe)
String? deviceId;
try {
final prefs = await SharedPreferences.getInstance();
deviceId = prefs.getString('cached_device_id');
} catch (e) {
print('Gagal membaca cache device_id: $e');
}
return UserModel(
id: user.id,
name: user.userMetadata?['name'] ?? user.email?.split('@').first ?? 'User',
email: user.email ?? '',
token: session.accessToken,
deviceId: deviceId,
);
}
return null;
}
}