From d6f9f4e16e392cbaa850976503f4ff8d798aaa78 Mon Sep 17 00:00:00 2001 From: Ollama Date: Sun, 7 Jun 2026 08:39:15 +0200 Subject: [PATCH] fix(security): Allow empty email addresses in customer import - Empty emails are now allowed (customers may not have email addresses) - Validation only applies when email is non-empty - Added test case for empty email acceptance This fixes a regression where FILTER_VALIDATE_EMAIL rejected empty strings, breaking imports for customers without email addresses. --- app/Controllers/Customers.php | 3 +- tests/Controllers/CustomersCsvImportTest.php | 40 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/app/Controllers/Customers.php b/app/Controllers/Customers.php index dd4492270..55a872a61 100644 --- a/app/Controllers/Customers.php +++ b/app/Controllers/Customers.php @@ -421,7 +421,8 @@ class Customers extends Persons if (sizeof($data) >= 16 && $consent) { $email = filter_var(strtolower($data[4]), FILTER_SANITIZE_EMAIL); - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + // Empty email is allowed, but if provided it must be valid + if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) { $failCodes[] = 'Row ' . $i . ': Invalid email format'; $i++; continue; diff --git a/tests/Controllers/CustomersCsvImportTest.php b/tests/Controllers/CustomersCsvImportTest.php index a79ed60c2..4c071ebfc 100644 --- a/tests/Controllers/CustomersCsvImportTest.php +++ b/tests/Controllers/CustomersCsvImportTest.php @@ -223,4 +223,44 @@ class CustomersCsvImportTest extends CIUnitTestCase unlink($tempFile); } + + public function testEmptyEmailIsAccepted(): void + { + $this->loginAsEmployee(); + + // Empty email should be allowed - customers may not have email addresses + $csvContent = [ + ['First Name', 'Last Name', 'Gender', 'Consent', 'Email', 'Phone', 'Address 1', 'Address 2', 'City', 'State', 'Zip', 'Country', 'Comments', 'Company', 'Account Number', 'Discount', 'Discount Type', 'Taxable'], + ['John', 'Doe', '1', '1', '', '555-1234', '123 Main St', '', 'Springfield', 'IL', '62701', 'US', '', '', '', '', '', ''] + ]; + + $tempFile = $this->createCsvFile($csvContent); + + $_FILES['file_path'] = [ + 'name' => 'test.csv', + 'type' => 'text/csv', + 'tmp_name' => $tempFile, + 'error' => UPLOAD_ERR_OK, + 'size' => filesize($tempFile) + ]; + + $result = $this->post('/customers/importCsvFile'); + + $result->assertOK(); + + $resultBody = json_decode($result->getJSON(), true); + $this->assertTrue($resultBody['success'], 'Import should succeed with empty email'); + + // Find customer by name since email is empty + $importedCustomer = $this->customer->select('customers.*, people.*') + ->join('people', 'people.person_id = customers.person_id') + ->where('first_name', 'John') + ->where('last_name', 'Doe') + ->first(); + + $this->assertNotNull($importedCustomer, 'Customer with empty email should be imported'); + $this->assertEquals('', $importedCustomer->email, 'Email should be empty string'); + + unlink($tempFile); + } } \ No newline at end of file