From 7bf8fd5eeb46823c1ee4348978c412706b57c28e Mon Sep 17 00:00:00 2001 From: snipe Date: Fri, 29 May 2026 10:55:53 +0100 Subject: [PATCH] Fixed #19106 - tighten up user accessor to treat null and empty string the same --- app/Importer/UserImporter.php | 2 +- app/Models/User.php | 2 +- .../Feature/Importing/Api/ImportUsersTest.php | 30 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/Importer/UserImporter.php b/app/Importer/UserImporter.php index cf33267c70..4aa92a0032 100644 --- a/app/Importer/UserImporter.php +++ b/app/Importer/UserImporter.php @@ -75,7 +75,7 @@ class UserImporter extends ItemImporter // Pull the records from the CSV to determine their values $this->item['id'] = trim($this->findCsvMatch($row, 'id')); $this->item['username'] = trim($this->findCsvMatch($row, 'username')); - $this->item['display_name'] = trim($this->findCsvMatch($row, 'display_name')); + $this->item['display_name'] = trim($this->findCsvMatch($row, 'display_name')) ?: null; $this->item['first_name'] = trim($this->findCsvMatch($row, 'first_name')); $this->item['last_name'] = trim($this->findCsvMatch($row, 'last_name')); $this->item['email'] = trim($this->findCsvMatch($row, 'email')); diff --git a/app/Models/User.php b/app/Models/User.php index 7c0faa5d3a..0b496f5fe2 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -323,7 +323,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo protected function displayName(): Attribute { return Attribute::make( - get: fn (mixed $value) => $value ?? $this->getFullNameAttribute(), + get: fn (mixed $value) => ($value !== null && $value !== '') ? $value : $this->getFullNameAttribute(), ); } diff --git a/tests/Feature/Importing/Api/ImportUsersTest.php b/tests/Feature/Importing/Api/ImportUsersTest.php index 80842a9beb..287927d0b8 100644 --- a/tests/Feature/Importing/Api/ImportUsersTest.php +++ b/tests/Feature/Importing/Api/ImportUsersTest.php @@ -434,4 +434,34 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ $this->assertEquals('updated@example.com', $target->refresh()->email); } + + #[Test] + public function display_name_falls_back_to_full_name_when_column_is_missing_from_csv(): void + { + $importFileBuilder = ImportFileBuilder::new()->forget('displayName'); + $row = $importFileBuilder->firstRow(); + $import = Import::factory()->users()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]); + + $this->actingAsForApi(User::factory()->superuser()->create()); + $this->importFileResponse(['import' => $import->id])->assertOk(); + + $newUser = User::query()->where('username', $row['username'])->sole(); + + $this->assertEquals("{$row['firstName']} {$row['lastName']}", $newUser->display_name); + } + + #[Test] + public function display_name_falls_back_to_full_name_when_column_is_empty_in_csv(): void + { + $importFileBuilder = ImportFileBuilder::new(['displayName' => '']); + $row = $importFileBuilder->firstRow(); + $import = Import::factory()->users()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]); + + $this->actingAsForApi(User::factory()->superuser()->create()); + $this->importFileResponse(['import' => $import->id])->assertOk(); + + $newUser = User::query()->where('username', $row['username'])->sole(); + + $this->assertEquals("{$row['firstName']} {$row['lastName']}", $newUser->display_name); + } }