fix: anonymize user first and last names

This commit is contained in:
2026-09-23 17:22:19 +02:00
parent e751eed4a0
commit 96b7b3f451
2 changed files with 65 additions and 0 deletions
+17
View File
@@ -97,6 +97,15 @@ class DatabaseAnonymizer
return $report;
}
/**
* Looked up by email alone, never by name: resolveIdentity() would register a name alias,
* and two accounts of the same person — an intended state here — would then collapse onto
* one synthetic identity and so onto one synthetic email, which User::$email is unique on.
*
* The names are only replaced where one is already set. Most accounts carry none until the
* BusPro import fills them in, and minting a name for those would turn an incomplete profile
* into one that looks complete while profileComplete still says otherwise.
*/
public function anonymizeUser(User $user): void
{
$identity = $this->resolveIdentity(
@@ -104,6 +113,14 @@ class DatabaseAnonymizer
);
$user->setEmail($identity['email']);
if ($this->hasReplaceableValue($user->getFirstName())) {
$user->setFirstName($identity['firstName']);
}
if ($this->hasReplaceableValue($user->getLastName())) {
$user->setLastName($identity['lastName']);
}
}
public function anonymizeNewsletterConsent(NewsletterConsent $consent): void
+48
View File
@@ -26,6 +26,8 @@ class DatabaseAnonymizerTest extends TestCase
);
$user = new User('[email protected]');
$user->setFirstName('Mia');
$user->setLastName('Muster');
$user->setPassword('plain-text-password');
$user->setPersonId(12345);
$user->setAddressId(67890);
@@ -162,6 +164,10 @@ class DatabaseAnonymizerTest extends TestCase
$service->anonymizeAccommodationBooking($booking);
self::assertStringEndsWith('@example.test', $user->getEmail());
self::assertNotSame('Mia', $user->getFirstName());
self::assertNotSame('Muster', $user->getLastName());
self::assertNotNull($user->getFirstName());
self::assertNotNull($user->getLastName());
self::assertSame('plain-text-password', $user->getPassword());
self::assertSame(12345, $user->getPersonId());
self::assertSame(67890, $user->getAddressId());
@@ -254,4 +260,46 @@ class DatabaseAnonymizerTest extends TestCase
self::assertNull($booking->getCity());
self::assertNull($booking->getRemarks());
}
/**
* Most accounts carry no name until the BusPro import fills one in. Minting one here would
* turn an incomplete profile into one that reads as complete while profileComplete still
* says otherwise.
*/
public function testAnonymizeUserLeavesUnsetNamesNull(): void
{
$service = new DatabaseAnonymizer(
$this->createStub(EntityManagerInterface::class),
new NullLogger(),
);
$user = new User('[email protected]');
$service->anonymizeUser($user);
self::assertStringEndsWith('@example.test', (string) $user->getEmail());
self::assertNull($user->getFirstName());
self::assertNull($user->getLastName());
}
/**
* Two accounts of the same person are an intended state, and User::$email is unique. The
* identity is therefore looked up by email alone: resolving it by name too would hand both
* accounts the same synthetic email and break the run on a constraint violation.
*/
public function testAnonymizeUserGivesTwoAccountsOfTheSamePersonDistinctEmails(): void
{
$service = new DatabaseAnonymizer(
$this->createStub(EntityManagerInterface::class),
new NullLogger(),
);
$private = (new User('[email protected]'))->setFirstName('Mia')->setLastName('Muster');
$staff = (new User('[email protected]'))->setFirstName('Mia')->setLastName('Muster');
$service->anonymizeUser($private);
$service->anonymizeUser($staff);
self::assertNotSame($private->getEmail(), $staff->getEmail());
}
}