From 148ca3af1d216cec2949a63bec61d6cbd97d1dbd Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Tue, 23 Jun 2026 17:25:29 +0300 Subject: [PATCH] Update: 2026-06-23 17:25:29 --- backend/auth/otp/providers.php | 43 ++++++++++------- backend/auth/otp/request.php | 5 ++ backend/schema_primary.sql | 8 ++-- .../views/admin/marketing/marketing_page.dart | 15 ++++-- siro_rider/ios/Podfile.lock | 46 ------------------- 5 files changed, 46 insertions(+), 71 deletions(-) diff --git a/backend/auth/otp/providers.php b/backend/auth/otp/providers.php index 3ede793..f30e7fb 100644 --- a/backend/auth/otp/providers.php +++ b/backend/auth/otp/providers.php @@ -52,8 +52,8 @@ function sendKazumiSms(string $receiver, string $otp): bool { */ function getNabehBearerToken(): ?string { global $redis; - - // 1. Try to read cached token from Redis (TTL 24 hours) + + // 1. Try fetching from Redis first if ($redis) { try { $cachedToken = $redis->get('nabeh_bearer_token'); @@ -61,16 +61,18 @@ function getNabehBearerToken(): ?string { return $cachedToken; } } catch (Exception $e) { - error_log("⚠️ [Nabeh Auth Redis] Error reading token: " . $e->getMessage()); + $msg = "⚠️ [Nabeh Auth Redis] Error reading token: " . $e->getMessage(); + error_log($msg); echo $msg . "
"; } } // 2. Token not cached, authenticate via Nabeh Login API $email = getenv('NABEH_EMAIL'); $password = getenv('NABEH_PASSWORD'); - + if (!$email || !$password) { - error_log("⚠️ [Nabeh Auth] Missing NABEH_EMAIL or NABEH_PASSWORD environment variables."); + $msg = "⚠️ [Nabeh Auth] Missing NABEH_EMAIL or NABEH_PASSWORD environment variables."; + error_log($msg); echo $msg . "
"; return null; } @@ -87,19 +89,24 @@ function getNabehBearerToken(): ?string { if ($response) { $decoded = json_decode($response, true); $token = $decoded['token'] ?? $decoded['message']['token'] ?? $decoded['jwt'] ?? $decoded['access_token'] ?? null; - if ($token) { - // Cache token in Redis for 24 hours (86400 seconds) + + // 3. Cache token in Redis for 24h if ($redis) { try { $redis->setex('nabeh_bearer_token', 86400, $token); } catch (Exception $e) { - error_log("⚠️ [Nabeh Auth Redis Cache Save] Error saving token: " . $e->getMessage()); + $msg = "⚠️ [Nabeh Auth Redis Cache Save] Error saving token: " . $e->getMessage(); + error_log($msg); echo $msg . "
"; } } return $token; } - error_log("❌ [Nabeh Auth] Failed to extract token from login response: " . $response); + $msg = "❌ [Nabeh Auth] Failed to extract token from login response: " . $response; + error_log($msg); echo $msg . "
"; + } else { + $msg = "❌ [Nabeh Auth] Empty response from login API cURL."; + error_log($msg); echo $msg . "
"; } return null; } @@ -115,7 +122,8 @@ function getNabehBearerToken(): ?string { function sendNabehOtp(string $receiver, string $otp, string $method = 'text'): bool { $bearerToken = getNabehBearerToken(); if (!$bearerToken) { - error_log("⚠️ [Nabeh OTP] Failed to obtain dynamic JWT Bearer token."); + $msg = "⚠️ [Nabeh OTP] Failed to obtain dynamic JWT Bearer token."; + error_log($msg); echo $msg . "
"; return false; } @@ -129,9 +137,6 @@ function sendNabehOtp(string $receiver, string $otp, string $method = 'text'): b } elseif ($method === 'image') { $type = 'image'; } - // elseif ($method === 'flash_call') { - // $type = 'flash_call'; - // } $apiUrl = 'https://nabeh.intaleqapp.com/api/otp/send'; $payload = [ @@ -150,7 +155,11 @@ function sendNabehOtp(string $receiver, string $otp, string $method = 'text'): b if ($decoded && ($decoded['success'] ?? false)) { return true; } - error_log("❌ [Nabeh OTP] API returned failure response: " . $response); + $msg = "❌ [Nabeh OTP] API returned failure response: " . $response; + error_log($msg); echo $msg . "
"; + } else { + $msg = "❌ [Nabeh OTP] Empty response from cURL."; + error_log($msg); echo $msg . "
"; } return false; } @@ -217,12 +226,14 @@ function curlCall(string $method, string $url, string $data, array $headers): ?s curl_close($ch); if ($error) { - error_log("⚠️ [OTP cURL] Error calling $url: $error"); + $msg = "⚠️ [OTP cURL] Error calling $url: $error"; + error_log($msg); echo $msg . "
"; return null; } if ($httpCode !== 200) { - error_log("⚠️ [OTP cURL] Non-200 HTTP code $httpCode from $url. Response: $response"); + $msg = "⚠️ [OTP cURL] Non-200 HTTP code $httpCode from $url. Response: $response"; + error_log($msg); echo $msg . "
"; } return $response; diff --git a/backend/auth/otp/request.php b/backend/auth/otp/request.php index ba442c8..e930ecb 100644 --- a/backend/auth/otp/request.php +++ b/backend/auth/otp/request.php @@ -2,6 +2,11 @@ // File: backend/auth/otp/request.php // Unified OTP request endpoint with geographical routing (Syria, Egypt, Jordan) +// Enable error reporting for debug +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); + require_once __DIR__ . '/../../core/bootstrap.php'; require_once __DIR__ . '/../../functions.php'; require_once __DIR__ . '/providers.php'; diff --git a/backend/schema_primary.sql b/backend/schema_primary.sql index 7fba399..153c273 100644 --- a/backend/schema_primary.sql +++ b/backend/schema_primary.sql @@ -206,7 +206,7 @@ CREATE TABLE `car_locations` ( /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' */ ; DELIMITER ;; -/*!50003 CREATE*/ /*!50017 DEFINER=`siroUserDB1`@`%`*/ /*!50003 TRIGGER `trg_before_insert_car_locations` BEFORE INSERT ON `car_locations` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50003 TRIGGER `trg_before_insert_car_locations` BEFORE INSERT ON `car_locations` FOR EACH ROW BEGIN SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326); END */;; DELIMITER ; @@ -223,7 +223,7 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' */ ; DELIMITER ;; -/*!50003 CREATE*/ /*!50017 DEFINER=`siroUserDB1`@`%`*/ /*!50003 TRIGGER `trg_before_update_car_locations` BEFORE UPDATE ON `car_locations` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50003 TRIGGER `trg_before_update_car_locations` BEFORE UPDATE ON `car_locations` FOR EACH ROW BEGIN IF NEW.latitude <> OLD.latitude OR NEW.longitude <> OLD.longitude THEN SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326); END IF; @@ -1144,7 +1144,7 @@ CREATE TABLE `passenger_opening_locations` ( /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' */ ; DELIMITER ;; -/*!50003 CREATE*/ /*!50017 DEFINER=`siroUserDB1`@`%`*/ /*!50003 TRIGGER `trg_before_insert_passenger_opening_locations` BEFORE INSERT ON `passenger_opening_locations` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50003 TRIGGER `trg_before_insert_passenger_opening_locations` BEFORE INSERT ON `passenger_opening_locations` FOR EACH ROW BEGIN SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326); END */;; DELIMITER ; @@ -1162,7 +1162,7 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' */ ; DELIMITER ;; -/*!50003 CREATE*/ /*!50017 DEFINER=`siroUserDB1`@`%`*/ /*!50003 TRIGGER `trg_before_update_passenger_opening_locations` BEFORE UPDATE ON `passenger_opening_locations` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50003 TRIGGER `trg_before_update_passenger_opening_locations` BEFORE UPDATE ON `passenger_opening_locations` FOR EACH ROW BEGIN IF NEW.latitude <> OLD.latitude OR NEW.longitude <> OLD.longitude THEN SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326); END IF; diff --git a/siro_admin/lib/views/admin/marketing/marketing_page.dart b/siro_admin/lib/views/admin/marketing/marketing_page.dart index ac9aafd..07abc8e 100644 --- a/siro_admin/lib/views/admin/marketing/marketing_page.dart +++ b/siro_admin/lib/views/admin/marketing/marketing_page.dart @@ -438,8 +438,6 @@ class MarketingPage extends StatelessWidget { padding: const EdgeInsets.only(bottom: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -571,6 +569,13 @@ class MarketingPage extends StatelessWidget { return const Center(child: CircularProgressIndicator(color: _accent)); } + return ListView.builder( + padding: const EdgeInsets.all(16), + itemCount: c.campaignsLog.length, + itemBuilder: (context, index) { + final log = c.campaignsLog[index]; + final channel = log['channel']?.toString().toUpperCase() ?? 'SMS'; + Color channelColor = _info; if (channel == 'SMS') channelColor = _success; if (channel == 'WHATSAPP') channelColor = const Color(0xFF25D366); @@ -602,19 +607,19 @@ class MarketingPage extends StatelessWidget { ), ), Text( - log['created_at'] ?? "", + log['created_at']?.toString() ?? "", style: const TextStyle(color: _textSecondary, fontSize: 11), ), ], ), const SizedBox(height: 12), Text( - log['campaign_name'] ?? "حملة استعادة تلقائية", + log['campaign_name']?.toString() ?? "حملة استعادة تلقائية", style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: _textPrimary), ), const SizedBox(height: 8), Text( - log['message_body'] ?? "", + log['message_body']?.toString() ?? "", style: const TextStyle(fontSize: 12, color: _textSecondary, height: 1.4), ), const SizedBox(height: 12), diff --git a/siro_rider/ios/Podfile.lock b/siro_rider/ios/Podfile.lock index 396abac..8fcd937 100644 --- a/siro_rider/ios/Podfile.lock +++ b/siro_rider/ios/Podfile.lock @@ -80,16 +80,6 @@ PODS: - GoogleDataTransport (10.1.0): - nanopb (~> 3.30910.0) - PromisesObjC (~> 2.4) - - GoogleMLKit/BarcodeScanning (7.0.0): - - GoogleMLKit/MLKitCore - - MLKitBarcodeScanning (~> 6.0.0) - - GoogleMLKit/MLKitCore (7.0.0): - - MLKitCommon (~> 12.0.0) - - GoogleToolboxForMac/Defines (4.2.1) - - GoogleToolboxForMac/Logger (4.2.1): - - GoogleToolboxForMac/Defines (= 4.2.1) - - "GoogleToolboxForMac/NSData+zlib (4.2.1)": - - GoogleToolboxForMac/Defines (= 4.2.1) - GoogleUtilities/AppDelegateSwizzler (8.1.1): - GoogleUtilities/Environment - GoogleUtilities/Logger @@ -138,26 +128,6 @@ PODS: - maplibre_gl (0.25.0): - Flutter - MapLibre (= 6.19.1) - - MLImage (1.0.0-beta6) - - MLKitBarcodeScanning (6.0.0): - - MLKitCommon (~> 12.0) - - MLKitVision (~> 8.0) - - MLKitCommon (12.0.0): - - GoogleDataTransport (~> 10.0) - - GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1) - - "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)" - - GoogleUtilities/Logger (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) - - GTMSessionFetcher/Core (< 4.0, >= 3.3.2) - - MLKitVision (8.0.0): - - GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1) - - "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)" - - GTMSessionFetcher/Core (< 4.0, >= 3.3.2) - - MLImage (= 1.0.0-beta6) - - MLKitCommon (~> 12.0) - - mobile_scanner (6.0.2): - - Flutter - - GoogleMLKit/BarcodeScanning (~> 7.0.0) - nanopb (3.30910.0): - nanopb/decode (= 3.30910.0) - nanopb/encode (= 3.30910.0) @@ -221,7 +191,6 @@ DEPENDENCIES: - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - location (from `.symlinks/plugins/location/ios`) - maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`) - - mobile_scanner (from `.symlinks/plugins/mobile_scanner/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`) @@ -248,16 +217,10 @@ SPEC REPOS: - FirebaseInstallations - FirebaseMessaging - GoogleDataTransport - - GoogleMLKit - - GoogleToolboxForMac - GoogleUtilities - GTMSessionFetcher - IOSSecuritySuite - MapLibre - - MLImage - - MLKitBarcodeScanning - - MLKitCommon - - MLKitVision - nanopb - PromisesObjC - RecaptchaInterop @@ -311,8 +274,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/location/ios" maplibre_gl: :path: ".symlinks/plugins/maplibre_gl/ios" - mobile_scanner: - :path: ".symlinks/plugins/mobile_scanner/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" permission_handler_apple: @@ -366,8 +327,6 @@ SPEC CHECKSUMS: flutter_webrtc: ec91d94b484ad49cf191ef93413f64a40ffd3b4c geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 - GoogleMLKit: eff9e23ec1d90ea4157a1ee2e32a4f610c5b3318 - GoogleToolboxForMac: d1a2cbf009c453f4d6ded37c105e2f67a32206d8 GoogleUtilities: 4f2618a4a1e762a1ee134a1e2323bba9843e06da GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 image_cropper: 64567491beea6cd1bc4b11948e2babb590de5826 @@ -380,11 +339,6 @@ SPEC CHECKSUMS: location: 155caecf9da4f280ab5fe4a55f94ceccfab838f8 MapLibre: 7f24faba45439f80ccb0f83393c29fa32cb81952 maplibre_gl: a2114567cbd1065866614fbd34dfb75ab782aaa2 - MLImage: 0ad1c5f50edd027672d8b26b0fee78a8b4a0fc56 - MLKitBarcodeScanning: 0a3064da0a7f49ac24ceb3cb46a5bc67496facd2 - MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d - MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e - mobile_scanner: af8f71879eaba2bbcb4d86c6a462c3c0e7f23036 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 permission_handler_apple: 92d754bbaa7361d436db2d6c3c1c2a0fdcec462e