Chepuhagram/lib/logic/auth_provider.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;
}
}
}