From 9f584a587481e52fb0fecd6161e0925b4a2e09ba Mon Sep 17 00:00:00 2001 From: Alberto Date: Wed, 11 Mar 2026 19:19:09 +0000 Subject: [PATCH] Eliminar creche_app/lib/core/auth_provider.dart --- creche_app/lib/core/auth_provider.dart | 162 ------------------------- 1 file changed, 162 deletions(-) delete mode 100644 creche_app/lib/core/auth_provider.dart diff --git a/creche_app/lib/core/auth_provider.dart b/creche_app/lib/core/auth_provider.dart deleted file mode 100644 index c90284d..0000000 --- a/creche_app/lib/core/auth_provider.dart +++ /dev/null @@ -1,162 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:supabase_flutter/supabase_flutter.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:local_auth/local_auth.dart'; -import 'package:geolocator/geolocator.dart'; -import 'package:http/http.dart' as http; -import '/models/profile.dart'; -import '/models/daily_access_approval.dart'; -import '/models/creche_settings.dart'; - -part 'auth_provider.g.dart'; - -// Provider para a sessão atual -@riverpod -Future currentSession(CurrentSessionRef ref) { - return Future.value(Supabase.instance.client.auth.currentSession); -} - -// Provider para o perfil do utilizador logado -@riverpod -Future currentProfile(CurrentProfileRef ref) async { - final session = await ref.watch(currentSessionProvider.future); - if (session == null) return null; - final data = await Supabase.instance.client - .from('profiles') - .select() - .eq('user_id', session.user.id) - .maybeSingle(); - if (data == null) return null; - return Profile.fromMap(data); -} - -@riverpod -class AuthNotifier extends _$AuthNotifier { - final _storage = const FlutterSecureStorage(); - final _localAuth = LocalAuthentication(); - - @override - Future build() async { - final token = await _storage.read(key: 'access_token'); - if (token != null) { - try { - await Supabase.instance.client.auth.setSession(token); - ref.invalidate(currentSessionProvider); - ref.invalidate(currentProfileProvider); - } catch (_) { - await _storage.delete(key: 'access_token'); - } - } - } - - Future signIn(String email, String password) async { - final supabase = Supabase.instance.client; - final response = await supabase.auth.signInWithPassword( - email: email, - password: password, - ); - await _storage.write( - key: 'access_token', value: response.session!.accessToken); - await _performSecurityChecks(); - ref.invalidate(currentSessionProvider); - ref.invalidate(currentProfileProvider); - } - - Future biometricSignIn() async { - final canAuthenticate = await _localAuth.canCheckBiometrics; - if (!canAuthenticate) throw Exception('Biometria não disponível'); - - final didAuthenticate = await _localAuth.authenticate( - localizedReason: 'Autentique para entrar no Diário do Candengue', - ); - if (!didAuthenticate) throw Exception('Falha na autenticação biométrica'); - - final token = await _storage.read(key: 'access_token'); - if (token == null) throw Exception('Sem sessão guardada. Faça login primeiro.'); - - await Supabase.instance.client.auth.setSession(token); - await _performSecurityChecks(); - ref.invalidate(currentSessionProvider); - ref.invalidate(currentProfileProvider); - } - - Future _performSecurityChecks() async { - final supabase = Supabase.instance.client; - final user = supabase.auth.currentUser; - if (user == null) throw Exception('Utilizador não autenticado'); - - // Verificar IP - final ipRes = await http.get(Uri.parse('https://api.ipify.org?format=text')); - final ip = ipRes.body.trim(); - - // Verificar localização - LocationPermission permission = await Geolocator.checkPermission(); - if (permission == LocationPermission.denied) { - permission = await Geolocator.requestPermission(); - } - final position = await Geolocator.getCurrentPosition( - desiredAccuracy: LocationAccuracy.high, - ); - - // Carregar configurações da creche - final settingsData = - await supabase.from('creche_settings').select().single(); - final settings = CrecheSettings.fromMap(settingsData); - - // Verificar IP (se lista não vazia) - if (settings.allowedIps.isNotEmpty && !settings.allowedIps.contains(ip)) { - throw Exception('Endereço IP não autorizado ($ip)'); - } - - // Verificar geofence (se coordenadas configuradas) - if (settings.geofenceLat != null && settings.geofenceLng != null) { - final distance = Geolocator.distanceBetween( - position.latitude, - position.longitude, - settings.geofenceLat!, - settings.geofenceLng!, - ); - if (distance > settings.geofenceRadiusMeters) { - throw Exception( - 'Fora da área permitida da creche (${distance.toInt()}m)'); - } - } - - // Verificar aprovação diária para teacher/staff - final profileData = await supabase - .from('profiles') - .select() - .eq('user_id', user.id) - .single(); - final profile = Profile.fromMap(profileData); - - if (profile.role == 'teacher' || profile.role == 'staff') { - final today = DateTime.now().toIso8601String().split('T')[0]; - final approvalData = await supabase - .from('daily_access_approvals') - .select() - .eq('user_id', profile.id) - .eq('approval_date', today) - .maybeSingle(); - - if (approvalData == null || - DailyAccessApproval.fromMap(approvalData).status != 'approved') { - // Lança exceção especial para redirecionar para sala de espera - throw WaitingApprovalException(); - } - } - } - - Future signOut() async { - await Supabase.instance.client.auth.signOut(); - await _storage.delete(key: 'access_token'); - ref.invalidate(currentSessionProvider); - ref.invalidate(currentProfileProvider); - } -} - -// Exceção especial para sala de espera -class WaitingApprovalException implements Exception { - @override - String toString() => 'Acesso pendente de aprovação da Diretora'; -}