'failure', 'message' => 'Method not allowed']); exit; } $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? ''; $expectedKey = getenv('NABEH_API_KEY') ?: ''; if (empty($apiKey) || $apiKey !== $expectedKey) { http_response_code(401); echo json_encode(['status' => 'failure', 'message' => 'Unauthorized: invalid API key']); exit; } // Rate limiting $rateLimitFile = __DIR__ . '/../logs/nabeh_rate_' . md5($_SERVER['REMOTE_ADDR'] ?? 'unknown') . '.lock'; $rateLimitWindow = 60; $rateLimitMax = 5; $now = time(); $attempts = []; if (file_exists($rateLimitFile)) { $attempts = json_decode(file_get_contents($rateLimitFile), true) ?: []; $attempts = array_filter($attempts, fn($t) => $t > ($now - $rateLimitWindow)); } if (count($attempts) >= $rateLimitMax) { http_response_code(429); echo json_encode(['status' => 'failure', 'message' => 'Too many requests. Try again later.']); exit; } $attempts[] = $now; file_put_contents($rateLimitFile, json_encode($attempts), LOCK_EX); $input = json_decode(file_get_contents('php://input'), true); if (!$input) { http_response_code(400); echo json_encode(['status' => 'failure', 'message' => 'Invalid JSON body']); exit; } $phone = preg_replace('/[^0-9]/', '', $input['phone'] ?? ''); $password = $input['password'] ?? substr(md5($phone . time()), 0, 12); $firstName = $input['first_name'] ?? $input['name_arabic'] ?? ''; $lastName = $input['last_name'] ?? '-'; $nameArabic = $input['name_arabic'] ?? $firstName; $nationalNumber = $input['national_number'] ?? ''; $birthdate = $input['birthdate'] ?? ''; $address = $input['address'] ?? ''; $gender = $input['gender'] ?? 'Male'; $site = $input['site'] ?? ''; $vin = $input['vin'] ?? ''; $carPlate = $input['car_plate'] ?? ''; $make = $input['make'] ?? ''; $model = $input['model'] ?? ''; $year = $input['year'] ?? ''; $color = $input['color'] ?? ''; $colorHex = $input['color_hex'] ?? '#000000'; $owner = $input['owner'] ?? ''; $fuel = $input['fuel'] ?? 'Petrol'; $expirationDate = $input['expiration_date'] ?? ''; $idFront = $input['id_front'] ?? $input['id_front_url'] ?? ''; $idBack = $input['id_back'] ?? $input['id_back_url'] ?? ''; $driverLicense = $input['driver_license'] ?? $input['driver_license_front_url'] ?? ''; $driverLicenseBack = $input['driver_license_back'] ?? $input['driver_license_back_url'] ?? ''; $carLicenseFront = $input['car_license_front'] ?? $input['vehicle_license_front_url'] ?? ''; $carLicenseBack = $input['car_license_back'] ?? $input['vehicle_license_back_url'] ?? ''; $criminalRecord = $input['criminal_record'] ?? $input['criminal_record_url'] ?? ''; $profilePicture = $input['profile_picture'] ?? ''; if (empty($phone)) { jsonError('Phone number is required'); } if (empty($firstName)) { jsonError('First name is required'); } if (empty($vin) || empty($carPlate) || empty($make) || empty($model) || empty($year)) { jsonError('Car details (vin, plate, make, model, year) are required'); } try { $db = Database::get('main'); $driverId = 'DRV' . date('YmdHis') . rand(100, 999); $hashedPassword = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]); global $encryptionHelper; $encryptedPhone = $encryptionHelper->encryptData($phone); $encryptedFirstName = $encryptionHelper->encryptData($firstName); $encryptedLastName = $encryptionHelper->encryptData($lastName); $encryptedNameArabic = $encryptionHelper->encryptData($nameArabic); $encryptedNationalNumber = !empty($nationalNumber) ? $encryptionHelper->encryptData($nationalNumber) : ''; $encryptedAddress = !empty($address) ? $encryptionHelper->encryptData($address) : ''; $encryptedGender = $encryptionHelper->encryptData($gender); $encryptedVin = $encryptionHelper->encryptData($vin); $encryptedCarPlate = $encryptionHelper->encryptData($carPlate); $encryptedOwner = $encryptionHelper->encryptData($owner); $encryptedSite = !empty($site) ? $encryptionHelper->encryptData($site) : $encryptedAddress; $nowDate = date('Y-m-d H:i:s'); $driverStmt = $db->prepare(" INSERT INTO driver ( id, phone, email, password, gender, first_name, last_name, name_arabic, national_number, address, site, birthdate, status, created_at, updated_at ) VALUES ( :id, :phone, :email, :password, :gender, :first_name, :last_name, :name_arabic, :national_number, :address, :site, :birthdate, 'yet', :created_at, :updated_at ) "); $driverStmt->execute([ ':id' => $driverId, ':phone' => $encryptedPhone, ':email' => $phone . '@intaleqapp.com', ':password' => $hashedPassword, ':gender' => $encryptedGender, ':first_name' => $encryptedFirstName, ':last_name' => $encryptedLastName, ':name_arabic' => $encryptedNameArabic, ':national_number' => $encryptedNationalNumber, ':address' => $encryptedAddress, ':site' => $encryptedSite, ':birthdate' => $birthdate, ':created_at' => $nowDate, ':updated_at' => $nowDate, ]); $carStmt = $db->prepare(" INSERT INTO CarRegistration ( driverID, vin, car_plate, make, model, year, expiration_date, color, owner, color_hex, fuel, isDefault, status, created_at, vehicle_category_id ) VALUES ( :driverID, :vin, :car_plate, :make, :model, :year, :expiration_date, :color, :owner, :color_hex, :fuel, 1, 'yet', :created_at, 1 ) "); $carStmt->execute([ ':driverID' => $driverId, ':vin' => $encryptedVin, ':car_plate' => $encryptedCarPlate, ':make' => $make, ':model' => $model, ':year' => $year, ':expiration_date' => $expirationDate ?: $nowDate, ':color' => $color, ':owner' => $encryptedOwner, ':color_hex' => $colorHex, ':fuel' => $fuel, ':created_at' => $nowDate, ]); $carRegId = $db->lastInsertId(); $docTypes = [ 'id_front' => $idFront, 'id_back' => $idBack, 'driver_license' => $driverLicense, 'driver_license_back' => $driverLicenseBack, 'car_license_front' => $carLicenseFront, 'car_license_back' => $carLicenseBack, 'criminal_record' => $criminalRecord, 'profile_picture' => $profilePicture, ]; $docStmt = $db->prepare(" INSERT INTO driver_documents (driverID, doc_type, image_name, link, upload_date) VALUES (:driverID, :doc_type, :image_name, :link, :upload_date) "); foreach ($docTypes as $docType => $link) { if (!empty($link)) { $docStmt->execute([ ':driverID' => $driverId, ':doc_type' => $docType, ':image_name' => $driverId . '_' . $docType, ':link' => $link, ':upload_date' => $nowDate, ]); } } error_log("[Nabeh Registration] New driver registered: {$driverId}, Phone: {$phone}"); echo json_encode([ 'status' => 'success', 'message' => [ 'status' => 'success', 'driverID' => $driverId, 'carRegID' => $carRegId, ] ], JSON_UNESCAPED_UNICODE); } catch (\Exception $e) { error_log("[Nabeh Registration Error] " . $e->getMessage()); http_response_code(500); echo json_encode([ 'status' => 'failure', 'message' => 'Internal server error: ' . $e->getMessage() ]); }