From d695a4e8127b7dddfee368cdd62d4a5e8d0e4e9d Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Mon, 29 Jun 2026 00:07:33 +0300 Subject: [PATCH] Update: 2026-06-29 00:07:33 --- backend/auth/syria/uploadImage.php | 2 +- backend/connect.php | 15 +++ backend/reset_driver.php | 10 -- siro_admin/lib/constant/links.dart | 19 ++-- .../admin/dashboard_controller.dart | 30 +++--- .../lib/controller/auth/otp_helper.dart | 5 +- siro_admin/lib/controller/functions/crud.dart | 26 +----- siro_driver/lib/constant/links.dart | 11 +++ .../auth/captin/phone_helper_controller.dart | 4 + siro_rider/lib/constant/links.dart | 11 +++ .../lib/controller/auth/otp_controller.dart | 4 + siro_service/lib/constant/links.dart | 11 +++ .../lib/controller/login_controller.dart | 6 ++ .../mainController/main_controller.dart | 3 +- .../review_driver_controller.dart | 93 ++++++++++++++++++- 15 files changed, 190 insertions(+), 60 deletions(-) delete mode 100644 backend/reset_driver.php diff --git a/backend/auth/syria/uploadImage.php b/backend/auth/syria/uploadImage.php index 697bca30..eb445350 100644 --- a/backend/auth/syria/uploadImage.php +++ b/backend/auth/syria/uploadImage.php @@ -72,7 +72,7 @@ $result['path'] = $simplePath; // --------- بناء الرابط العام --------- $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; -$host = getenv('APP_DOMAIN') ?: ($_SERVER['HTTP_HOST'] ?? 'api.siromove.com'); +$host = $_SERVER['HTTP_HOST'] ?? (getenv('APP_DOMAIN') ?: 'api.siromove.com'); $basePath = rtrim(dirname(dirname(dirname($_SERVER['SCRIPT_NAME']))), '/'); $url = "$protocol://$host{$basePath}/auth/uploads/{$country}/{$result['filename']}"; diff --git a/backend/connect.php b/backend/connect.php index ffb0d31b..ca40671b 100644 --- a/backend/connect.php +++ b/backend/connect.php @@ -5,6 +5,21 @@ // ============================================================ require_once __DIR__ . '/core/bootstrap.php'; + +// --------- تحقق من تطابق المنطقة (Region Mismatch Guard) --------- +$requestHost = $_SERVER['HTTP_HOST'] ?? ''; +$appDomain = getenv('APP_DOMAIN') ?: ''; +if (!empty($appDomain) && !empty($requestHost) && strtolower($requestHost) !== strtolower($appDomain)) { + if ($requestHost !== 'localhost' && !preg_match('/^127\.0\.0\./', $requestHost)) { + http_response_code(400); + exit(json_encode([ + 'status' => 'failure', + 'error_code' => 'REGION_MISMATCH', + 'message' => "Region mismatch: Request host '$requestHost' does not match server domain '$appDomain'." + ])); + } +} + require_once __DIR__ . '/functions.php'; // 1. Rate Limiting and JWT Authentication diff --git a/backend/reset_driver.php b/backend/reset_driver.php deleted file mode 100644 index af3519e6..00000000 --- a/backend/reset_driver.php +++ /dev/null @@ -1,10 +0,0 @@ -prepare("UPDATE drivers SET status = 'pending_review' WHERE driverID = 'TEST202606252141546122'"); - $stmt->execute(); - echo "Driver status updated to pending_review successfully!"; -} catch (Exception $e) { - echo "Error: " . $e->getMessage(); -} diff --git a/siro_admin/lib/constant/links.dart b/siro_admin/lib/constant/links.dart index 316c0e6b..b8f4f2ec 100644 --- a/siro_admin/lib/constant/links.dart +++ b/siro_admin/lib/constant/links.dart @@ -460,14 +460,17 @@ class AppLink { static String addNotesPassenger = "$serviceApp/addNotesPassenger.php"; static String getPackages = "$serviceApp/getPackages.php"; static String updatePackages = "$serviceApp/updatePackages.php"; - ////// - static String sendSms = "https://sms.kazumi.me/api/sms/send-sms"; - static String senddlr = "https://sms.kazumi.me/api/sms/send-dlr"; - static String sendvalidity = "https://sms.kazumi.me/api/sms/send-validity"; - static String sendmany = "https://sms.kazumi.me/api/sms/send-many"; - static String checkCredit = "https://sms.kazumi.me/api/sms/check-credit"; - static String getSender = "$server/auth/sms/getSender.php"; - static String checkStatus = "https://sms.kazumi.me/api/sms/check-status"; static String updatePhoneInvalidSMSPassenger = "$server/auth/sms/updatePhoneInvalidSMSPassenger.php"; + + static String detectCountryFromPhone(String phone) { + final clean = phone.replaceAll(RegExp(r'[^0-9]'), ''); + if (clean.startsWith('962')) return 'Jordan'; + if (clean.startsWith('963')) return 'Syria'; + if (clean.startsWith('20')) return 'Egypt'; + if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan'; + if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria'; + if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt'; + return ''; + } } diff --git a/siro_admin/lib/controller/admin/dashboard_controller.dart b/siro_admin/lib/controller/admin/dashboard_controller.dart index ead4709c..1f482a48 100644 --- a/siro_admin/lib/controller/admin/dashboard_controller.dart +++ b/siro_admin/lib/controller/admin/dashboard_controller.dart @@ -86,21 +86,21 @@ class DashboardController extends GetxController { update(); } - sendSMSMethod() async { - if (formKey.currentState!.validate()) { - for (var phoneNumber in box.read(BoxName.tokensDrivers)['message']) { - // for (var i = 0; i < 2; i++) { - await CRUD().sendSmsEgypt( - phoneNumber['phone'].toString(), - // box.read(BoxName.tokensDrivers)['message'][i]['phone'].toString(), - smsText.text, - ); - // print('CRUD().phoneDriversTest.: ${phoneNumber['phone']}'); - Future.delayed(const Duration(microseconds: 20)); - } - Get.back(); - } - } + // sendSMSMethod() async { + // if (formKey.currentState!.validate()) { + // for (var phoneNumber in box.read(BoxName.tokensDrivers)['message']) { + // // for (var i = 0; i < 2; i++) { + // await CRUD().sendSmsEgypt( + // phoneNumber['phone'].toString(), + // // box.read(BoxName.tokensDrivers)['message'][i]['phone'].toString(), + // smsText.text, + // ); + // // print('CRUD().phoneDriversTest.: ${phoneNumber['phone']}'); + // Future.delayed(const Duration(microseconds: 20)); + // } + // Get.back(); + // } + // } @override void onInit() async { diff --git a/siro_admin/lib/controller/auth/otp_helper.dart b/siro_admin/lib/controller/auth/otp_helper.dart index 48da7e67..224e1800 100644 --- a/siro_admin/lib/controller/auth/otp_helper.dart +++ b/siro_admin/lib/controller/auth/otp_helper.dart @@ -26,7 +26,10 @@ class OtpHelper extends GetxController { /// إرسال OTP static Future sendOtp(String phoneNumber) async { try { - // await CRUD().getJWT(); + final detectedCountry = AppLink.detectCountryFromPhone(phoneNumber); + if (detectedCountry.isNotEmpty) { + await box.write(BoxName.countryCode, detectedCountry); + } final response = await CRUD().post( link: _sendOtpUrl, payload: {'receiver': phoneNumber, 'user_type': 'admin'}, diff --git a/siro_admin/lib/controller/functions/crud.dart b/siro_admin/lib/controller/functions/crud.dart index cc6b2be1..42bee14e 100644 --- a/siro_admin/lib/controller/functions/crud.dart +++ b/siro_admin/lib/controller/functions/crud.dart @@ -48,7 +48,8 @@ class CRUD { final jwt = decodedResponse1['jwt']; Log.print('jwt: $jwt'); await box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); - await storage.write(key: BoxName.jwt, value: X.c(X.c(X.c(jwt, cn), cC), cs)); + await storage.write( + key: BoxName.jwt, value: X.c(X.c(X.c(jwt, cn), cC), cs)); // await AppInitializer().getKey(); } } @@ -448,8 +449,7 @@ class CRUD { return response.statusCode; } - Future allMethodForAI(String prompt, driverID, imagePath) async { - } + Future allMethodForAI(String prompt, driverID, imagePath) async {} Map>> getAllTextValuesWithLineNumbers( Map json) { @@ -569,7 +569,6 @@ class CRUD { return response.statusCode; } - Future kazumiSMS({ required String link, Map? payload, @@ -594,25 +593,6 @@ class CRUD { } else {} } - Future sendSmsEgypt(String phone, otp) async { - // String sender = await getSender(); - var headers = {'Content-Type': 'application/json'}; - var body = jsonEncode({ - "username": "Sefer", - "password": "E)Pu=an/@Z", - "message": otp, - "language": "e", - "sender": "Sefer Egy", - "receiver": phone - }); - - await _client.post( - Uri.parse(AppLink.sendSms), - body: body, - headers: headers, - ); - } - Future postPayMob({ required String link, Map? payload, diff --git a/siro_driver/lib/constant/links.dart b/siro_driver/lib/constant/links.dart index e99a5ce7..f9675a7d 100755 --- a/siro_driver/lib/constant/links.dart +++ b/siro_driver/lib/constant/links.dart @@ -622,4 +622,15 @@ class AppLink { "$serviceApp/getComplaintAllData.php"; static String get getComplaintAllDataForDriver => "$serviceApp/getComplaintAllDataForDriver.php"; + + static String detectCountryFromPhone(String phone) { + final clean = phone.replaceAll(RegExp(r'[^0-9]'), ''); + if (clean.startsWith('962')) return 'Jordan'; + if (clean.startsWith('963')) return 'Syria'; + if (clean.startsWith('20')) return 'Egypt'; + if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan'; + if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria'; + if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt'; + return ''; + } } diff --git a/siro_driver/lib/controller/auth/captin/phone_helper_controller.dart b/siro_driver/lib/controller/auth/captin/phone_helper_controller.dart index d225fc06..0357ccfc 100644 --- a/siro_driver/lib/controller/auth/captin/phone_helper_controller.dart +++ b/siro_driver/lib/controller/auth/captin/phone_helper_controller.dart @@ -24,6 +24,10 @@ class PhoneAuthHelper { /// Sends an OTP to the provided phone number. static Future sendOtp(String phoneNumber) async { try { + final detectedCountry = AppLink.detectCountryFromPhone(phoneNumber); + if (detectedCountry.isNotEmpty) { + await box.write(BoxName.countryCode, detectedCountry); + } final fixedPhone = CountryLogic.formatCurrentCountryPhone(phoneNumber); Log.print('fixedPhone: $fixedPhone'); diff --git a/siro_rider/lib/constant/links.dart b/siro_rider/lib/constant/links.dart index 825485d1..0725d56f 100644 --- a/siro_rider/lib/constant/links.dart +++ b/siro_rider/lib/constant/links.dart @@ -526,4 +526,15 @@ class AppLink { static String get checkStatus => "https://sms.kazumi.me/api/sms/check-status"; static String get updatePhoneInvalidSMSPassenger => "$server/auth/sms/updatePhoneInvalidSMSPassenger.php"; + + static String detectCountryFromPhone(String phone) { + final clean = phone.replaceAll(RegExp(r'[^0-9]'), ''); + if (clean.startsWith('962')) return 'Jordan'; + if (clean.startsWith('963')) return 'Syria'; + if (clean.startsWith('20')) return 'Egypt'; + if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan'; + if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria'; + if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt'; + return ''; + } } diff --git a/siro_rider/lib/controller/auth/otp_controller.dart b/siro_rider/lib/controller/auth/otp_controller.dart index ed3b71e0..c58c5272 100644 --- a/siro_rider/lib/controller/auth/otp_controller.dart +++ b/siro_rider/lib/controller/auth/otp_controller.dart @@ -23,6 +23,10 @@ class PhoneAuthHelper { /// Sends an OTP to the provided phone number. static Future sendOtp(String phoneNumber) async { try { + final detectedCountry = AppLink.detectCountryFromPhone(phoneNumber); + if (detectedCountry.isNotEmpty) { + await box.write(BoxName.countryCode, detectedCountry); + } // إصلاح الرقم قبل الإرسال final fixedPhone = CountryLogic.formatCurrentCountryPhone(phoneNumber); diff --git a/siro_service/lib/constant/links.dart b/siro_service/lib/constant/links.dart index 57d5b595..8f44ce0d 100644 --- a/siro_service/lib/constant/links.dart +++ b/siro_service/lib/constant/links.dart @@ -188,4 +188,15 @@ class AppLink { static String addCartoDriver = "$serviceApp/addCartoDriver.php"; static String getRegisrationCar = "$ride/RegisrationCar/get.php"; static String updateRegisrationCar = "$ride/RegisrationCar/update.php"; + + static String detectCountryFromPhone(String phone) { + final clean = phone.replaceAll(RegExp(r'[^0-9]'), ''); + if (clean.startsWith('962')) return 'Jordan'; + if (clean.startsWith('963')) return 'Syria'; + if (clean.startsWith('20')) return 'Egypt'; + if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan'; + if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria'; + if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt'; + return ''; + } } diff --git a/siro_service/lib/controller/login_controller.dart b/siro_service/lib/controller/login_controller.dart index f57d84c3..9e9d7b23 100644 --- a/siro_service/lib/controller/login_controller.dart +++ b/siro_service/lib/controller/login_controller.dart @@ -22,6 +22,12 @@ class LoginController extends GetxController { final FlutterSecureStorage storage = const FlutterSecureStorage(); void login() async { + final emailStr = email.text.trim(); + final detectedCountry = AppLink.detectCountryFromPhone(emailStr); + if (detectedCountry.isNotEmpty) { + await box.write(BoxName.countryCode, detectedCountry); + } + // Ensure fingerprint is ready String fingerprint = box.read(BoxName.fingerPrint) ?? ''; if (fingerprint.isEmpty) { diff --git a/siro_service/lib/controller/mainController/main_controller.dart b/siro_service/lib/controller/mainController/main_controller.dart index 77b0f2b2..b4c36f61 100644 --- a/siro_service/lib/controller/mainController/main_controller.dart +++ b/siro_service/lib/controller/mainController/main_controller.dart @@ -50,7 +50,8 @@ class MainController extends GetxController { @override void onInit() { super.onInit(); - // refreshDashboardStats(); // Removed to save data consumption at start + final country = box.read('countryCode')?.toString() ?? 'Jordan'; + Log.print('🌍 [SIRO-SERVICE-STARTUP] Current countryCode stored in box: $country'); } Future refreshDashboardStats() async { diff --git a/siro_service/lib/controller/mainController/review_driver_controller.dart b/siro_service/lib/controller/mainController/review_driver_controller.dart index e391b2e7..43e31791 100644 --- a/siro_service/lib/controller/mainController/review_driver_controller.dart +++ b/siro_service/lib/controller/mainController/review_driver_controller.dart @@ -123,6 +123,42 @@ class ReviewDriverController extends GetxController { }; List> getFieldsForTab(String tabKey) { + final countryCode = country; + if (countryCode == 'Syria') { + if (tabKey == 'driver_license_front') { + return [ + ['licenseTypeController', 'License Type', false, false, false, false], + [ + 'licenseIssueDateController', + 'License Issue Date', + true, + false, + false, + false + ], + [ + 'expiryDateController', + 'License Expiry Date', + true, + false, + false, + false + ], + ]; + } + if (tabKey == 'driver_license_back') { + return [ + [ + 'licenseCategoriesController', + 'License Categories', + false, + false, + false, + false + ], + ]; + } + } return fieldConfig[tabKey] ?? []; } @@ -161,6 +197,10 @@ class ReviewDriverController extends GetxController { driverId.value = args['driverId'] ?? ''; phone.value = args['phone'] ?? ''; } + if (country == 'Jordan' || country == 'Egypt') { + docUrls.remove('driver_license_back'); + } + _initializeDocUrls(); fetchData(); } @@ -210,13 +250,64 @@ class ReviewDriverController extends GetxController { } } + String reconstructDocumentUrl(String originalLink, String docType) { + if (originalLink.isEmpty) { + return "${AppLink.server}/auth/syria/driversDocs/syria.intaleq.xyz-${driverId.value}-$docType.jpg"; + } + + try { + final origUri = Uri.parse(originalLink); + final query = origUri.query; + final path = origUri.path; + + if (path.contains('secure_image.php')) { + return "${AppLink.server}/secure_image.php?$query"; + } + + if (path.contains('auth/syria/driversDocs/')) { + final parts = path.split('auth/syria/driversDocs/'); + final filename = parts.last; + return "${AppLink.server}/auth/syria/driversDocs/$filename"; + } + + if (originalLink.startsWith('http://') || + originalLink.startsWith('https://')) { + final serverUri = Uri.parse(AppLink.server); + final host = serverUri.host; + + final newUri = Uri( + scheme: 'https', + host: host, + path: path, + query: query.isNotEmpty ? query : null, + ); + return newUri.toString(); + } + + final cleanPath = path.startsWith('/') ? path : '/$path'; + return "${AppLink.server}$cleanPath${query.isNotEmpty ? '?$query' : ''}"; + } catch (e) { + if (originalLink.startsWith('http://')) { + return originalLink.replaceFirst('http://', 'https://'); + } + return originalLink; + } + } + + void _initializeDocUrls() { + for (var key in docUrls.keys) { + docUrls[key]!.value = reconstructDocumentUrl('', key); + } + } + void _populateDocUrls(dynamic docs) { if (docs is List) { for (var doc in docs) { if (doc is Map && doc['doc_type'] != null && doc['link'] != null) { String type = doc['doc_type'].toString(); if (docUrls.containsKey(type)) { - docUrls[type]!.value = doc['link'].toString(); + docUrls[type]!.value = + reconstructDocumentUrl(doc['link'].toString(), type); } } }