init
This commit is contained in:
commit
e833bcaec4
224 files changed
+11812
No files matched your search
@@ -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}');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user