120 lines
3.6 KiB
Dart
120 lines
3.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
import 'dart:convert';
|
|
import '/core/constants.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:chepuhagram/domain/services/api_service.dart';
|
|
import 'package:chepuhagram/data/datasources/ws_client.dart';
|
|
|
|
class AuthProvider extends ChangeNotifier {
|
|
bool _isLoading = false;
|
|
bool get isLoading => _isLoading;
|
|
|
|
int? _currentUserId;
|
|
int? get currentUserId => _currentUserId;
|
|
|
|
final _storage = const FlutterSecureStorage();
|
|
final _client = http.Client();
|
|
final ApiService _apiService = ApiService();
|
|
final SocketService _socketService = SocketService();
|
|
|
|
Future<void> initRealtime() async {
|
|
final token = await _apiService.getAccessToken();
|
|
if (token != null) {
|
|
_socketService.connect(token);
|
|
}
|
|
}
|
|
|
|
void closeRealtime() {
|
|
_socketService.disconnect();
|
|
}
|
|
SocketService get socketService => _socketService;
|
|
|
|
Future<bool> login(String username, String password) async {
|
|
_isLoading = true;
|
|
notifyListeners();
|
|
|
|
try {
|
|
final response = await _client.post(
|
|
Uri.http(AppConstants.baseUrl, 'auth/login'),
|
|
body: {'username': username, 'password': password},
|
|
);
|
|
|
|
final decodedResponse =
|
|
jsonDecode(utf8.decode(response.bodyBytes)) as Map;
|
|
|
|
if (response.statusCode == 200) {
|
|
await _storage.write(
|
|
key: 'access_token',
|
|
value: decodedResponse['access_token'],
|
|
);
|
|
await _storage.write(
|
|
key: 'refresh_token',
|
|
value: decodedResponse['refresh_token'],
|
|
);
|
|
await _storage.write(
|
|
key: 'user_id',
|
|
value: decodedResponse['user_id'].toString(),
|
|
);
|
|
_currentUserId = decodedResponse['user_id'];
|
|
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
return true;
|
|
} else {
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
final error = decodedResponse['detail'] ?? 'Ошибка запроса';
|
|
throw Exception(error);
|
|
}
|
|
} catch (e) {
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> logout() async {
|
|
final mode = await _storage.read(key: 'theme_mode');
|
|
final color = await _storage.read(key: 'accent_color');
|
|
await _storage.deleteAll();
|
|
if (mode != null) {
|
|
await _storage.write(key: 'theme_mode', value: mode);
|
|
}
|
|
if (color != null) {
|
|
await _storage.write(key: 'accent_color', value: color);
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<bool> tryAutoLogin() async {
|
|
final token = await _apiService.getAccessToken();
|
|
if (token == null) return false;
|
|
|
|
try {
|
|
final response = await _client
|
|
.get(
|
|
Uri.http(AppConstants.baseUrl, 'users/me'),
|
|
headers: {'Authorization': 'Bearer $token'},
|
|
)
|
|
.timeout(const Duration(seconds: 5));
|
|
|
|
if (response.statusCode == 200) {
|
|
return true;
|
|
} else if (response.statusCode == 401) {
|
|
bool isUpdated = await _apiService.refreshToken();
|
|
return isUpdated;
|
|
} else {
|
|
// Если токен протух (401), чистим память
|
|
//await logout();
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
// Если сервер недоступен (ошибка сети),
|
|
// в мессенджерах обычно всё равно пускают в приложение (offline mode),
|
|
// но для простоты сейчас вернем true, если токен физически есть.
|
|
return true;
|
|
}
|
|
}
|
|
}
|