import 'dart:io' show Platform; import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../models/user.dart'; import 'api_client.dart'; /// Session state + token persistence. The token is a Sanctum personal /// access token, named per-device on the backend (see `/login`'s /// `device_name`) so a user could later revoke one device without others. class AuthService extends ChangeNotifier { AuthService(this._apiClient); final ApiClient _apiClient; final _storage = const FlutterSecureStorage(); static const _tokenKey = 'auth_token'; User? _user; bool _isLoading = true; // true until restoreSession() resolves once at startup User? get user => _user; bool get isLoading => _isLoading; bool get isAuthenticated => _user != null; /// Call once at app startup: restores a saved token and validates it /// against `/me` — a saved token can be stale if it was revoked /// server-side (e.g. logged out from another device's session list). Future restoreSession() async { final token = await _storage.read(key: _tokenKey); if (token == null) { _isLoading = false; notifyListeners(); return; } _apiClient.setToken(token); try { final json = await _apiClient.get('/me'); _user = User.fromJson(json['data'] as Map); } on ApiException { await _storage.delete(key: _tokenKey); _apiClient.setToken(null); } _isLoading = false; notifyListeners(); } Future login(String email, String password) async { final json = await _apiClient.post('/login', { 'email': email, 'password': password, 'device_name': _deviceName(), }); final token = json['token'] as String; await _storage.write(key: _tokenKey, value: token); _apiClient.setToken(token); _user = User.fromJson(json['user'] as Map); notifyListeners(); } Future logout() async { try { await _apiClient.post('/logout'); } on ApiException { // Token may already be invalid server-side (expired/revoked) — // still clear local state so the user isn't stuck logged in. } await _storage.delete(key: _tokenKey); _apiClient.setToken(null); _user = null; notifyListeners(); } String _deviceName() { if (kIsWeb) return 'web'; if (Platform.isIOS) return 'iOS device'; if (Platform.isAndroid) return 'Android device'; return Platform.operatingSystem; } }