This commit is contained in:
Riccardo Usardi committed 2025-07-18 22:24:01 +02:00
commit e833bcaec4
224 files changed
+11812

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'auth.service.dart';
class ApiService {
static const String _baseUrl = 'http://192.168.0.9:5000'; // cambia qui
// Token memorizzato in memoria (per sessione)
static String? _token;
static String? get token => _token;
static String get baseUrl => _baseUrl;
// Login con Basic Auth e salvataggio token
static Future<String> login(String username, String password) async {
final url = Uri.parse('$_baseUrl/User/login');
// Header con Basic Auth
String basicAuth =
'Basic ${base64Encode(utf8.encode('$username:$password'))}';
final response = await http.get(
url,
headers: {
'Authorization': basicAuth,
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_token = data['access_token']; // salva il token in memoria
print('Token ricevuto: $_token'); // stampa in console
AuthService.instance.saveToken(_token!);
return '${response.statusCode}';
} else {
throw Exception(
'Login fallito: ${response.statusCode} - ${response.body}');
}
}
static Future<dynamic> checkLogin() async {
final token = AuthService.instance.token;
print('Token corrente: $token'); // stampa in console
if (token == null) {
print('Token non disponibile. Effettua il login prima.'); // stampa in console
throw Exception('Token non disponibile. Effettua il login prima.');
}
final url = Uri.parse('$_baseUrl/Test/cklogin');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final object = jsonDecode(response.body);
print('Risposta cklogin: $object'); // stampa in console
return object;
} else {
throw Exception(
'Errore checkLogin: ${response.statusCode} - ${response.body}');
}
}
}
+42
View File
@@ -0,0 +1,42 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:u_vineyard/services/auth.service.dart';
import '../entities/user.dart';
import 'api.service.dart';
class UserService {
static final String _baseUrl = ApiService.baseUrl;
Future<User?> userProfile(int userId) async {
String token = AuthService.instance.token ?? '';
if (token.isEmpty) {
print('Token non disponibile. Effettua il login prima.');
return null; // Gestisci il caso in cui il token non sia disponibile
}
try {
final url = Uri.parse('$_baseUrl/Test/cklogin');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
// Decodifica la risposta JSON
final Map<String, dynamic> jsonMap = json.decode(response.body);
// Crea e restituisce un oggetto User usando il costruttore fromJson
return User.fromJson(jsonMap);
} else {
// Gestisci le risposte con stato diverso da 200 (es. 404, 500)
print('Errore: La richiesta non è andata a buon fine. Status code: ${response.statusCode}');
return null;
}
} catch (e) {
// Gestisci eventuali eccezioni (es. nessuna connessione, URL errato)
print('Errore durante il recupero dei dati: $e');
return null;
}
}
}
+125
View File
@@ -0,0 +1,125 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:local_auth/local_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
static final AuthService _instance = AuthService._internal();
static AuthService get instance => _instance;
AuthService._internal();
final _secureStorage = const FlutterSecureStorage(); // Per piattaforme mobili
// Non inizializzare SharedPreferences qui direttamente, perché è async
String? _token;
static const String _tokenKey = 'AuthToken'; // Chiave comune per storage
String? get token => _token;
// Questa funzione ora serve solo per la logica specifica mobile (es. biometrica)
// Non usarla per decidere dove salvare il token, usa kIsWeb direttamente
Future<bool> _isMobileOrDesktopPlatform() async {
if (kIsWeb) return false;
// Android, iOS, Windows, Linux, macOS
//final deviceInfo = DeviceInfoPlugin();
if (defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.windows ||
defaultTargetPlatform == TargetPlatform.linux ||
defaultTargetPlatform == TargetPlatform.macOS) {
return true;
}
return false;
}
// Nuova funzione per salvare il token
Future<void> saveToken(String token) async {
_token = token; // Aggiorna il token in memoria
print('AuthToken: Tentativo di salvataggio token: $token');
if (kIsWeb) {
// Per Web: usa SharedPreferences (che su web usa localStorage)
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_tokenKey, token);
print('AuthToken: Token salvato in SharedPreferences (Web).');
} else if (await _isMobileOrDesktopPlatform()) {
// Per Mobile/Desktop: usa FlutterSecureStorage
await _secureStorage.write(key: _tokenKey, value: token);
print('AuthToken: Token salvato in FlutterSecureStorage (Mobile/Desktop).');
}
}
// Nuova funzione per caricare il token (senza biometria)
Future<String?> _loadTokenFromStorage() async {
if (kIsWeb) {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_tokenKey);
} else if (await _isMobileOrDesktopPlatform()) {
return _secureStorage.read(key: _tokenKey);
}
return null; // Caso non supportato
}
Future<bool> loadTokenWithBiometric() async {
// Prima, prova sempre a caricare il token dallo storage generale
// Questo è il token che verra' utilizzato se la biometria fallisce o non è disponibile.
_token = await _loadTokenFromStorage();
if (_token != null && !await _isMobileOrDesktopPlatform()) {
// Se siamo su web e il token è stato caricato, l'autenticazione è implicita (no biometria)
print('AuthToken: Token caricato da storage (Web), biometria non applicabile.');
return true;
}
// Se non è una piattaforma mobile/desktop supportata per la biometria, o se il token non c'è,
// o se la biometria non è disponibile/non supportata, gestisci di conseguenza.
if (!await _isMobileOrDesktopPlatform()) {
print('AuthToken: Biometria non disponibile su questa piattaforma.');
return false;
}
try {
final auth = LocalAuthentication();
final canAuth = await auth.canCheckBiometrics || await auth.isDeviceSupported();
if (!canAuth) {
print('AuthToken: Dispositivo non supporta biometria.');
// Se la biometria non è supportata, ma un token esiste, consideralo loggato
return _token != null;
}
final authenticated = await auth.authenticate(
localizedReason: 'Autenticati per accedere',
options: const AuthenticationOptions(
biometricOnly: true,
stickyAuth: true,
),
);
if (authenticated) {
final stored = await _secureStorage.read(key: _tokenKey); // Rileggi da secure storage
_token = stored; // Aggiorna il token in memoria con quello autenticato biometricamente
print('AuthToken: Biometria riuscita, token da storage sicuro: $_token');
return stored != null;
} else {
print('AuthToken: Autenticazione biometrica fallita.');
_token = null; // Se la biometria fallisce, resetta il token in memoria
}
} catch (e) {
debugPrint('AuthToken: Errore autenticazione biometrica: $e');
_token = null; // In caso di errore, resetta il token
}
return false;
}
Future<void> clear() async {
_token = null;
print('AuthToken: Tentativo di cancellazione token.');
if (kIsWeb) {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_tokenKey);
print('AuthToken: Token cancellato da SharedPreferences (Web).');
} else if (await _isMobileOrDesktopPlatform()) {
await _secureStorage.delete(key: _tokenKey);
print('AuthToken: Token cancellato da FlutterSecureStorage (Mobile/Desktop).');
}
}
}
@@ -0,0 +1,40 @@
// utils/polygon_area_calculator.dart
import 'package:latlong2/latlong.dart';
import 'dart:math';
class PolygonAreaCalculatorService {
// Costante per il raggio medio della Terra in metri (WGS84 ellipsoid semi-major axis)
static const double _earthRadius = 6378137.0;
/// Calcola l'area di un poligono su una sfera (Terra) in ettari.
/// Implementa una versione della formula di Shoelace per coordinate geodetiche.
/// Restituisce 0.0 se i punti sono meno di 3.
static double calculateAreaInHectares(List<LatLng> points) {
if (points.length < 3) return 0.0;
double area = 0.0;
// La formula di Shoelace richiede che il poligono sia chiuso (primo punto = ultimo punto)
List<LatLng> closedPoints = List.from(points);
if (closedPoints.first != closedPoints.last) {
closedPoints.add(closedPoints.first);
}
for (int i = 0; i < closedPoints.length - 1; i++) {
LatLng p1 = closedPoints[i];
LatLng p2 = closedPoints[i + 1];
// Conversione delle latitudini e longitudini da gradi a radianti
double lat1Rad = p1.latitude * pi / 180.0;
double lon1Rad = p1.longitude * pi / 180.0;
double lat2Rad = p2.latitude * pi / 180.0;
double lon2Rad = p2.longitude * pi / 180.0;
// Formula per l'area di un segmento sferico
area += (lon2Rad - lon1Rad) * (2 + sin(lat1Rad) + sin(lat2Rad));
}
area = (area * _earthRadius * _earthRadius / 2.0).abs();
// Converti da metri quadrati a ettari (1 ettaro = 10000 m^2)
return area / 10000.0;
}
}
@@ -0,0 +1,40 @@
// utils/polygon_area_calculator.dart
import 'package:latlong2/latlong.dart';
import 'dart:math';
class PolygonAreaCalculator {
// Costante per il raggio medio della Terra in metri (WGS84 ellipsoid semi-major axis)
static const double _earthRadius = 6378137.0;
/// Calcola l'area di un poligono su una sfera (Terra) in ettari.
/// Implementa una versione della formula di Shoelace per coordinate geodetiche.
/// Restituisce 0.0 se i punti sono meno di 3.
static double calculateAreaInHectares(List<LatLng> points) {
if (points.length < 3) return 0.0;
double area = 0.0;
// La formula di Shoelace richiede che il poligono sia chiuso (primo punto = ultimo punto)
List<LatLng> closedPoints = List.from(points);
if (closedPoints.first != closedPoints.last) {
closedPoints.add(closedPoints.first);
}
for (int i = 0; i < closedPoints.length - 1; i++) {
LatLng p1 = closedPoints[i];
LatLng p2 = closedPoints[i + 1];
// Conversione delle latitudini e longitudini da gradi a radianti
double lat1Rad = p1.latitude * pi / 180.0;
double lon1Rad = p1.longitude * pi / 180.0;
double lat2Rad = p2.latitude * pi / 180.0;
double lon2Rad = p2.longitude * pi / 180.0;
// Formula per l'area di un segmento sferico
area += (lon2Rad - lon1Rad) * (2 + sin(lat1Rad) + sin(lat2Rad));
}
area = (area * _earthRadius * _earthRadius / 2.0).abs();
// Converti da metri quadrati a ettari (1 ettaro = 10000 m^2)
return area / 10000.0;
}
}