import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:mileograph_flutter/objects/objects.dart'; import 'package:mileograph_flutter/services/apiService.dart'; class AuthService extends ChangeNotifier { final ApiService api; static const _tokenKey = 'auth_token'; bool _restoring = false; // secure storage instance final FlutterSecureStorage _storage = const FlutterSecureStorage(); AuthService({required this.api}); AuthenticatedUserData? _user; bool get isLoggedIn => _user != null; String? get token => _user?.access_token; String? get userId => _user?.user_id; String? get username => _user?.username; String? get fullName => _user?.full_name; void setLoginData({ required String userId, required String username, required String fullName, required String accessToken, required String email, }) { _user = AuthenticatedUserData( user_id: userId, username: username, full_name: fullName, access_token: accessToken, email: email, ); _persistToken(accessToken); notifyListeners(); } Future login(String username, String password) async { final formData = { 'grant_type': 'password', 'username': username, 'password': password, 'scope': '', 'client_id': 'string', 'client_secret': 'string', }; // 1. Get token final tokenResponse = await api.postForm('/token', formData); final accessToken = tokenResponse['access_token']; // 2. Get user details final userResponse = await api.get( '/users/me', headers: { 'Authorization': 'Bearer $accessToken', 'accept': 'application/json', }, ); // 3. Populate state setLoginData( userId: userResponse['user_id'], username: userResponse['username'], fullName: userResponse['full_name'], accessToken: accessToken, email: userResponse['email'], ); } Future tryRestoreSession() async { if (_restoring || _user != null) return; _restoring = true; try { // read token from secure storage final token = await _storage.read(key: _tokenKey); if (token == null || token.isEmpty) return; final userResponse = await api.get( '/users/me', headers: { 'Authorization': 'Bearer $token', 'accept': 'application/json', }, ); setLoginData( userId: userResponse['user_id'], username: userResponse['username'], fullName: userResponse['full_name'], accessToken: token, email: userResponse['email'], ); } catch (_) { await _clearToken(); } finally { _restoring = false; } } Future _persistToken(String token) async { await _storage.write(key: _tokenKey, value: token); } Future _clearToken() async { await _storage.delete(key: _tokenKey); } Future register({ required String username, required String email, required String fullName, required String password, String inviteCode = '', }) async { final formData = { 'user_name': username, 'email': email, 'full_name': fullName, 'password': password, 'invitation_code': inviteCode, 'empty': '', 'empty2': '', }; await api.postForm('/register', formData); } Future handleTokenExpired() async { _user = null; await _clearToken(); notifyListeners(); } void logout() { handleTokenExpired(); // reuse } }