Files
twilio-wp-plugin/mobile/lib/services/auth_service.dart

109 lines
3.0 KiB
Dart
Raw Normal View History

import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../models/user.dart';
import 'api_client.dart';
class AuthService {
final ApiClient _api;
final FlutterSecureStorage _storage = const FlutterSecureStorage();
Timer? _refreshTimer;
AuthService(this._api);
Future<User> login(String serverUrl, String username, String password,
{String? fcmToken}) async {
await _api.setBaseUrl(serverUrl);
final response = await _api.dio.post(
'/auth/login',
data: {
'username': username,
'password': password,
if (fcmToken != null) 'fcm_token': fcmToken,
},
options: Options(receiveTimeout: const Duration(seconds: 60)),
);
final data = response.data;
if (data['success'] != true) {
throw Exception(data['message'] ?? 'Login failed');
}
await _storage.write(key: 'access_token', value: data['access_token']);
await _storage.write(key: 'refresh_token', value: data['refresh_token']);
await _storage.write(key: 'user_data', value: jsonEncode(data['user']));
_scheduleRefresh(data['expires_in'] as int? ?? 3600);
return User.fromJson(data['user']);
}
Future<User?> tryRestoreSession() async {
final token = await _storage.read(key: 'access_token');
if (token == null) return null;
await _api.restoreBaseUrl();
if (_api.dio.options.baseUrl.isEmpty) return null;
try {
final response = await _api.dio.get('/agent/status');
if (response.statusCode != 200) return null;
final userData = await _storage.read(key: 'user_data');
if (userData != null) {
return User.fromJson(jsonDecode(userData) as Map<String, dynamic>);
}
return null;
} catch (_) {
return null;
}
}
Future<void> refreshToken() async {
final refreshToken = await _storage.read(key: 'refresh_token');
if (refreshToken == null) throw Exception('No refresh token');
final response = await _api.dio.post('/auth/refresh', data: {
'refresh_token': refreshToken,
});
final data = response.data;
if (data['success'] != true) {
throw Exception('Token refresh failed');
}
await _storage.write(key: 'access_token', value: data['access_token']);
if (data['refresh_token'] != null) {
await _storage.write(key: 'refresh_token', value: data['refresh_token']);
}
_scheduleRefresh(data['expires_in'] as int? ?? 3600);
}
void _scheduleRefresh(int expiresInSeconds) {
_refreshTimer?.cancel();
// Refresh 2 minutes before expiry
final refreshIn = Duration(seconds: expiresInSeconds - 120);
if (refreshIn.isNegative) return;
_refreshTimer = Timer(refreshIn, () async {
try {
await refreshToken();
} catch (_) {}
});
}
Future<void> logout() async {
_refreshTimer?.cancel();
try {
await _api.dio.post('/auth/logout');
} catch (_) {}
await _storage.deleteAll();
}
void dispose() {
_refreshTimer?.cancel();
}
}