diff --git a/backend/Admin/Staff/add.php b/backend/Admin/Staff/add.php index e0f1083..49742fb 100644 --- a/backend/Admin/Staff/add.php +++ b/backend/Admin/Staff/add.php @@ -32,6 +32,7 @@ $fingerprint = filterRequest("fingerprint") ?: ''; $gender = filterRequest("gender") ?? 'Male'; $birthdate = filterRequest("birthdate") ?? date('Y-m-d'); $site = filterRequest("site") ?? 'main'; +$country = filterRequest("country") ?? 'Jordan'; if (empty($name) || empty($password) || empty($role)) { jsonError("Missing required fields (name, password, role)."); @@ -70,8 +71,8 @@ try { } else { // الإضافة لجدول المستخدمين (خدمة العملاء) // أضفنا site و last_name (كقيمة افتراضية فارغة إذا لم تتوفر) - $sql = "INSERT INTO users (id, fingerprint, fingerprint_hash, phone, email, gender, password, birthdate, user_type, first_name, last_name, site, created_at) - VALUES (:id, :fp, :fp_hash, :phone, :email, :gender, :pass, :bdate, 'service', :fname, :lname, :site, NOW())"; + $sql = "INSERT INTO users (id, fingerprint, fingerprint_hash, phone, email, gender, password, birthdate, user_type, first_name, last_name, site, country, created_at) + VALUES (:id, :fp, :fp_hash, :phone, :email, :gender, :pass, :bdate, 'service', :fname, :lname, :site, :country, NOW())"; $stmt = $con->prepare($sql); $stmt->execute([ ':id' => $uniqueId, @@ -84,7 +85,8 @@ try { ':bdate' => $birthdate, ':fname' => $encName, ':lname' => '', // last_name is empty for now - ':site' => $site + ':site' => $site, + ':country' => $country ]); } diff --git a/backend/Admin/Staff/add_super_admin.php b/backend/Admin/Staff/add_super_admin.php new file mode 100644 index 0000000..96f659d --- /dev/null +++ b/backend/Admin/Staff/add_super_admin.php @@ -0,0 +1,63 @@ + 'Access denied. Admin key required.'])); +// } + +$con = Database::get('main'); + +$name = filterRequest('name') ?: 'Super Admin'; +$email = filterRequest('email') ?: ''; +$phone = filterRequest('phone') ?: ''; +$fingerprint = filterRequest('fingerprint') ?: ''; +$password = filterRequest('password') ?: bin2hex(random_bytes(8)); + +try { + $hashedPass = password_hash($password, PASSWORD_DEFAULT); + $encName = $encryptionHelper->encryptData($name); + $encPhone = $phone ? $encryptionHelper->encryptData($phone) : ''; + $encEmail = $email ? $encryptionHelper->encryptData($email) : ''; + $encFp = $fingerprint ? $encryptionHelper->encryptData($fingerprint) : ''; + $fpHash = $fingerprint ? hash('sha256', $fingerprint) : ''; + $uniqueId = bin2hex(random_bytes(16)); + + $check = $con->prepare("SELECT id FROM adminUser WHERE role = 'super_admin' LIMIT 1"); + $check->execute(); + if ($check->fetch()) { + echo "

⚠️ Super Admin already exists.

"; + exit; + } + + $sql = "INSERT INTO adminUser (id, fingerprint, fingerprint_hash, name, phone, email, password, role, created_at) + VALUES (:id, :fp, :fp_hash, :name, :phone, :email, :pass, 'super_admin', NOW())"; + $stmt = $con->prepare($sql); + $stmt->execute([ + ':id' => $uniqueId, + ':fp' => $encFp, + ':fp_hash' => $fpHash, + ':name' => $encName, + ':phone' => $encPhone, + ':email' => $encEmail, + ':pass' => $hashedPass, + ]); + + if ($stmt->rowCount() > 0) { + echo "

✅ Super Admin created successfully!

"; + echo "

ID: $uniqueId

"; + echo "

Name: $name

"; + echo "

Password: $password

"; + echo "

⚠️ Save this password. Delete this file after use.

"; + } else { + echo "

❌ Failed to create Super Admin.

"; + } +} catch (Exception $e) { + echo "

❌ Error: " . htmlspecialchars($e->getMessage()) . "

"; +} diff --git a/backend/serviceapp/getDriverDetailsForActivate.php b/backend/serviceapp/getDriverDetailsForActivate.php index 2ce4aa9..c714199 100644 --- a/backend/serviceapp/getDriverDetailsForActivate.php +++ b/backend/serviceapp/getDriverDetailsForActivate.php @@ -5,7 +5,7 @@ $driverId = filterRequest("driverId"); $sql = "SELECT d.*, cr.* FROM `driver` d - JOIN `CarRegistration` cr ON cr.driverID = d.id + LEFT JOIN `CarRegistration` cr ON cr.driverID = d.id WHERE d.id = :driverId "; $stmt = $con->prepare($sql); diff --git a/backend/serviceapp/getDriverNotCompleteRegistration.php b/backend/serviceapp/getDriverNotCompleteRegistration.php index d458def..a33edbd 100644 --- a/backend/serviceapp/getDriverNotCompleteRegistration.php +++ b/backend/serviceapp/getDriverNotCompleteRegistration.php @@ -7,14 +7,14 @@ $sql = "SELECT notesForDriverService.note FROM phone_verification -INNER JOIN -- نستخدم INNER JOIN لضمان جلب من لديهم ملاحظات فقط +INNER JOIN `notesForDriverService` ON `notesForDriverService`.`phone` = `phone_verification`.`phone_number` WHERE `notesForDriverService`.`note` != 'delete' ORDER BY - `phone_verification`.`created_at` DESC -- الترتيب حسب تاريخ التحقق لأنه العمود الموجود + `phone_verification`.`created_at` DESC LIMIT 400; "; @@ -24,7 +24,6 @@ $stmt->execute(); if ($stmt->rowCount() > 0) { $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - // فك تشفير أرقام الهواتف فقط للإخراج foreach ($rows as &$row) { if (!empty($row['phone'])) { $row['phone'] = $encryptionHelper->decryptData($row['phone']); @@ -42,4 +41,3 @@ if ($stmt->rowCount() > 0) { } else { jsonError("No Phone verified yet found"); } -?> \ No newline at end of file diff --git a/backend/serviceapp/login.php b/backend/serviceapp/login.php index f424a39..7a60dea 100644 --- a/backend/serviceapp/login.php +++ b/backend/serviceapp/login.php @@ -105,10 +105,6 @@ try { $expires_in = $ttl; } - // توليد مفتاح HMAC فريد للمستخدم (للتوافق مع CRUD الجديد) - $hmacKey = hash_hmac('sha256', (string)$user['id'], getenv('SECRET_KEY_HMAC')); - - // ✅ FIX H-05: لا نعيد مفتاح HMAC أبداً (يُحسب على العميل بنفس المعادلة) printSuccess([ "message" => "Login successful", "data" => $user, diff --git a/siro_admin/lib/controller/admin/staff_controller.dart b/siro_admin/lib/controller/admin/staff_controller.dart index ad09666..2f78444 100644 --- a/siro_admin/lib/controller/admin/staff_controller.dart +++ b/siro_admin/lib/controller/admin/staff_controller.dart @@ -18,6 +18,7 @@ class StaffController extends GetxController { String selectedGender = 'Male'; String selectedRole = 'service'; // 'admin' or 'service' + String selectedCountry = 'Jordan'; bool isLoading = false; @@ -43,6 +44,7 @@ class StaffController extends GetxController { "birthdate": birthdateController.text.trim(), "fingerprint": fingerprint, "site": "main", // القيمة الافتراضية للفرع + "country": selectedCountry, }, ); diff --git a/siro_admin/lib/views/admin/staff/add_staff_page.dart b/siro_admin/lib/views/admin/staff/add_staff_page.dart index 057bf89..a167ad3 100644 --- a/siro_admin/lib/views/admin/staff/add_staff_page.dart +++ b/siro_admin/lib/views/admin/staff/add_staff_page.dart @@ -87,6 +87,14 @@ class AddStaffPage extends StatelessWidget { ), ], ), + const SizedBox(height: 16), + _buildDropdown( + label: "البلد", + value: controller.selectedCountry, + items: const ['Jordan', 'Syria', 'Egypt'], + onChanged: (val) => controller.selectedCountry = val!, + fillColor: inputColor, + ), const SizedBox(height: 40), GetBuilder( builder: (controller) => SizedBox( diff --git a/siro_admin/macos/Podfile.lock b/siro_admin/macos/Podfile.lock index d88ecd3..ba42875 100644 --- a/siro_admin/macos/Podfile.lock +++ b/siro_admin/macos/Podfile.lock @@ -105,6 +105,8 @@ PODS: - nanopb/encode (= 3.30910.0) - nanopb/decode (3.30910.0) - nanopb/encode (3.30910.0) + - package_info_plus (0.0.1): + - FlutterMacOS - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS @@ -127,6 +129,7 @@ DEPENDENCIES: - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) @@ -167,6 +170,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral local_auth_darwin: :path: Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin sqflite_darwin: @@ -191,11 +196,12 @@ SPEC CHECKSUMS: FirebaseSessions: b9a92c1c51bbb81e78fc3142cda6d925d700f8e7 flutter_image_compress_macos: e68daf54bb4bf2144c580fd4d151c949cbf492f0 flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54 - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 + package_info_plus: 122abb51244f66eead59ce7c9c200d6b53111779 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 diff --git a/siro_service/lib/controller/login_controller.dart b/siro_service/lib/controller/login_controller.dart index a6b2a89..6b53d69 100644 --- a/siro_service/lib/controller/login_controller.dart +++ b/siro_service/lib/controller/login_controller.dart @@ -140,6 +140,9 @@ class LoginController extends GetxController { await storage.write(key: 'password', value: pass); await box.write(BoxName.employeename, userData['first_name']); await box.write(BoxName.password, pass); + if (userData['country'] != null) { + await box.write(BoxName.countryCode, userData['country']); + } Get.offAll(() => Main()); } else { diff --git a/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart b/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart index 65cb87b..7dbf62b 100644 --- a/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart +++ b/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart @@ -144,21 +144,22 @@ class DriversCantRegister extends StatelessWidget { }, ), - // Edit button → go to registration form - buildActionButton( - icon: CupertinoIcons - .pencil_ellipsis_rectangle, - color: AppColor.gold, - onPressed: () { - Get.to( - () => const ReviewDriverPage(), - arguments: { - "phone": driver['phone_number'], - "driverId": driver['driverId'], - }, - ); - }, - ), + // Edit button → go to review page (only if driverId exists) + if (driver['driverId'] != null) + buildActionButton( + icon: CupertinoIcons + .pencil_ellipsis_rectangle, + color: AppColor.gold, + onPressed: () { + Get.to( + () => const ReviewDriverPage(), + arguments: { + "phone": driver['phone_number'], + "driverId": driver['driverId'], + }, + ); + }, + ), buildActionButton( icon: CupertinoIcons .pencil_ellipsis_rectangle, diff --git a/siro_service/lib/controller/mainController/review_driver_controller.dart b/siro_service/lib/controller/mainController/review_driver_controller.dart index b6af42a..49e3e82 100644 --- a/siro_service/lib/controller/mainController/review_driver_controller.dart +++ b/siro_service/lib/controller/mainController/review_driver_controller.dart @@ -48,7 +48,7 @@ class ReviewDriverController extends GetxController { 'profile_picture': Icons.person, }; - String get country => box.read('countryCode')?.toString() ?? 'Syria'; + String get country => box.read('countryCode')?.toString() ?? 'Jordan'; static const Map>> fieldConfig = { 'id_front': [