Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-09 16:56:13 +03:00
parent 95e2e4f35d
commit b64debaa88
1058 changed files with 164327 additions and 113928 deletions
+91 -30
View File
@@ -1,12 +1,12 @@
import 'dart:async';
import 'dart:convert';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:tripz_rider/constant/links.dart';
import 'package:tripz_rider/controller/auth/login_controller.dart';
import 'package:tripz_rider/main.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/auth/login_controller.dart';
import 'package:siro_rider/main.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:tripz_rider/env/env.dart';
import 'package:siro_rider/env/env.dart';
import '../../constant/api_key.dart';
@@ -24,7 +24,6 @@ class CRUD {
final NetGuard _netGuard = NetGuard();
final _client = SslPinning.createPinnedClient();
static bool _isRefreshingJWT = false;
static String _lastErrorSignature = '';
static DateTime _lastErrorTimestamp = DateTime(2000);
static const Duration _errorLogDebounceDuration = Duration(minutes: 1);
@@ -98,31 +97,50 @@ class CRUD {
Future<String> _getJwt() async {
try {
final String? encryptedJwt = await storage.read(key: BoxName.jwt);
if (encryptedJwt == null || encryptedJwt.isEmpty) {
final String? fallback = box.read(BoxName.jwt);
final jwt = await storage.read(key: BoxName.jwt);
if (jwt == null || jwt.toString().isEmpty) {
// إذا كان التخزين الآمن فارغاً، نحاول استخراج التوكن القديم من GetStorage للركاب القدامى
final fallback = box.read(BoxName.jwt);
if (fallback != null) {
return r(fallback).toString().split(Env.addd)[0];
try {
return r(fallback).toString().split(Env.addd)[0]; // فك تشفير القديم
} catch (_) {
return fallback.toString(); // ربما تم تخزينه بدون تشفير
}
}
return '';
}
return r(encryptedJwt).toString().split(Env.addd)[0];
} catch (e) {
Log.print('Error reading JWT from SecureStorage: $e');
final String? fallback = box.read(BoxName.jwt);
if (fallback != null) {
return r(fallback).toString().split(Env.addd)[0];
// التحقق السريع إذا كان التوكن لا يزال مشفراً (يبدأ برموز غريبة وليس ey)
if (!jwt.startsWith('ey')) {
try {
return r(jwt).toString().split(Env.addd)[0];
} catch (_) {}
}
return jwt;
} catch (_) {
return '';
}
}
// ═══════════════════════════════════════════════════════════════
// _ensureJwt — يضمن وجود توكن صالح قبل الإرسال
// ═══════════════════════════════════════════════════════════════
Future<String> _ensureJwt() async {
String token = await _getJwt();
if (_isJwtValid(token)) return token;
final ok = await Get.put(LoginController()).getJWT();
if (!ok) return '';
return await _getJwt();
}
/// Centralized request handler with retry for weak networks.
/// For Syria (3G): 60s total timeout, 3 retries, exponential backoff.
Future<dynamic> _makeRequest({
required String link,
Map<String, dynamic>? payload,
required Map<String, String> headers,
bool allowRefresh = true,
}) async {
const totalTimeout = Duration(seconds: 60);
@@ -180,17 +198,33 @@ class CRUD {
}
}
// 429 → السيرفر رافض بسبب الضغط؛ ممنوع نجدّد التوكن أو نعيد المحاولة
if (sc == 429) {
Log.print('🛑 [RES] 429 rate limited — $link');
return 'rate_limited';
}
// 401 → تجديد التوكن مرة واحدة ثم إعادة الطلب مرة واحدة فقط
if (sc == 401) {
// تخطي تجديد التوكن لـ endpoints غير حرجة (مثل تسجيل الأخطاء)
final isNonCritical = link.contains('errorApp.php');
if (!_isRefreshingJWT && !isNonCritical) {
_isRefreshingJWT = true;
try {
await Get.put(LoginController()).getJWT();
} finally {
_isRefreshingJWT = false;
}
}
return 'token_expired';
if (isNonCritical || !allowRefresh) return 'token_expired';
final refreshed = await Get.put(LoginController()).getJWT();
if (!refreshed) return 'token_expired';
final newToken = await _getJwt();
if (newToken.isEmpty) return 'token_expired';
// إعادة الطلب بالتوكن الجديد — allowRefresh: false يمنع أي تكرار إضافي
final retryHeaders = Map<String, String>.from(headers)
..['Authorization'] = 'Bearer $newToken';
return await _makeRequest(
link: link,
payload: payload,
headers: retryHeaders,
allowRefresh: false,
);
}
if (sc >= 500) {
@@ -206,7 +240,14 @@ class CRUD {
required String link,
Map<String, dynamic>? payload,
}) async {
String token = await _getJwt();
String token = await _ensureJwt();
if (token.isEmpty) {
// إذا فشل الحصول على توكن، لا ترسل الطلب للباك إند لأنّه سيرفض حتماً.
// باستثناء تسجيل الدخول لأنه لا يحتاج توكن
if (!link.contains('login') && !link.contains('errorApp.php')) {
return 'token_expired';
}
}
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
@@ -221,7 +262,12 @@ class CRUD {
required String link,
Map<String, dynamic>? payload,
}) async {
String token = await _getJwt();
String token = await _ensureJwt();
if (token.isEmpty) {
if (!link.contains('login') && !link.contains('errorApp.php')) {
return 'token_expired';
}
}
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
@@ -238,6 +284,16 @@ class CRUD {
// التغيير: إضافة X-Device-FP header
// 3 headers معاً: JWT + HMAC + FP
// ═══════════════════════════════════════════════════════════════
/// توكن المحفظة صار يُخزَّن ويُعاد استخدامه. لو رفضه السيرفر (توكن
/// مُلغى أو تغيّر سرّ التوقيع) نمسح النسخة المخزّنة كي يُطلب توكن
/// جديد في المحاولة التالية بدل أن نعلق على توكن ميت.
void _invalidateWalletJwtIfRejected(dynamic result) {
if (result == 'token_expired') {
Log.print('🗑️ توكن المحفظة مرفوض — مسح النسخة المخزّنة.');
box.remove(BoxName.walletJwt);
}
}
Future<dynamic> postWallet({
required String link,
Map<String, dynamic>? payload,
@@ -251,11 +307,13 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
'X-Device-FP': _getFpHeader(),
};
Log.print('headers: $headers');
Log.print('payload: $payload');
Log.print('link: $link');
return await _makeRequest(link: link, payload: payload, headers: headers);
final result =
await _makeRequest(link: link, payload: payload, headers: headers);
_invalidateWalletJwtIfRejected(result);
return result;
}
Future<dynamic> getWallet({
@@ -272,7 +330,10 @@ class CRUD {
'X-Device-FP': _getFpHeader(),
};
return await _makeRequest(link: link, payload: payload, headers: headers);
final result =
await _makeRequest(link: link, payload: payload, headers: headers);
_invalidateWalletJwtIfRejected(result);
return result;
}
// =======================================================================