109 lines
3.2 KiB
Dart
109 lines
3.2 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import '../constants/api_constants.dart';
|
|
import '../main.dart';
|
|
import 'app_lifecycle_service.dart';
|
|
|
|
class AuthService {
|
|
static const FlutterSecureStorage _storage = FlutterSecureStorage();
|
|
static const String _tokenKey = 'jwt_token';
|
|
static const String _userDataKey = 'user_data';
|
|
|
|
static Future<Map<String, dynamic>> login(
|
|
String phoneNumberOrUsername,
|
|
String password,
|
|
) async {
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse('${ApiConstants.baseUrl}${ApiConstants.loginEndpoint}'),
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: jsonEncode({
|
|
'phoneNumberOrUsername': phoneNumberOrUsername,
|
|
'password': password,
|
|
}),
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
final token = data['token'];
|
|
|
|
if (token != null) {
|
|
await _storage.write(key: _tokenKey, value: token);
|
|
return {'success': true};
|
|
}
|
|
return {'success': false, 'message': 'No token received'};
|
|
} else if (response.statusCode == 403 || response.statusCode == 400) {
|
|
return {'success': false, 'message': 'Invalid credentials'};
|
|
} else if (response.statusCode == 401) {
|
|
return {'success': false, 'message': 'Invalid credentials'};
|
|
} else {
|
|
return {
|
|
'success': false,
|
|
'message': 'Server error (${response.statusCode})',
|
|
};
|
|
}
|
|
} catch (e) {
|
|
print('Login error: $e');
|
|
return {
|
|
'success': false,
|
|
'message': 'Network error. Please check your connection.',
|
|
};
|
|
}
|
|
}
|
|
|
|
static Future<String?> getToken() async {
|
|
return await _storage.read(key: _tokenKey);
|
|
}
|
|
|
|
static Future<void> saveToken(String token) async {
|
|
await _storage.write(key: _tokenKey, value: token);
|
|
}
|
|
|
|
static Future<bool> isLoggedIn() async {
|
|
final token = await getToken();
|
|
return token != null && token.isNotEmpty;
|
|
}
|
|
|
|
static Future<void> logout() async {
|
|
// Stop all polling services when logging out
|
|
AppLifecycleService.dispose();
|
|
await _storage.delete(key: _tokenKey);
|
|
await _storage.delete(key: _userDataKey);
|
|
}
|
|
|
|
static Future<Map<String, String>> getAuthHeaders() async {
|
|
final token = await getToken();
|
|
return {
|
|
'Content-Type': 'application/json',
|
|
if (token != null) 'Authorization': 'Bearer $token',
|
|
};
|
|
}
|
|
|
|
static Future<void> saveUserData(Map<String, dynamic> userData) async {
|
|
await _storage.write(key: _userDataKey, value: jsonEncode(userData));
|
|
}
|
|
|
|
static Future<Map<String, dynamic>?> getCachedUserData() async {
|
|
final userData = await _storage.read(key: _userDataKey);
|
|
if (userData != null) {
|
|
return jsonDecode(userData);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
static Future<void> clearUserData() async {
|
|
await _storage.delete(key: _userDataKey);
|
|
}
|
|
|
|
static Future<void> handleAuthenticationError() async {
|
|
await logout();
|
|
|
|
final context = navigatorKey.currentContext;
|
|
if (context != null && context.mounted) {
|
|
Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
|
|
}
|
|
}
|
|
}
|