diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index 095dfd54..9f602a80 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -170,7 +170,7 @@ class SecurityController extends AbstractController $this->addFlash('success', 'pw_reset.new_pw.success'); $repo = $em->getRepository(User::class); - $u = $repo->findOneBy(['name' => $data['username']]); + $u = $repo->findByUsername($data['username']); $event = new SecurityEvent($u); /** @var EventDispatcher $eventDispatcher */ $eventDispatcher->dispatch($event, SecurityEvents::PASSWORD_RESET); diff --git a/src/DataFixtures/UserFixtures.php b/src/DataFixtures/UserFixtures.php index 171f671e..d34a83cd 100644 --- a/src/DataFixtures/UserFixtures.php +++ b/src/DataFixtures/UserFixtures.php @@ -54,6 +54,7 @@ class UserFixtures extends Fixture implements DependentFixtureInterface $user = new User(); $user->setName('user'); $user->setNeedPwChange(false); + $user->setEmail('user@invalid.invalid'); $user->setFirstName('Test')->setLastName('User'); $user->setPassword($this->encoder->hashPassword($user, 'test')); $user->setGroup($this->getReference(GroupFixtures::USERS)); @@ -66,6 +67,9 @@ class UserFixtures extends Fixture implements DependentFixtureInterface $manager->persist($noread); $manager->flush(); + + //Ensure that the anonymous user has the ID 0 + $manager->getRepository(User::class)->changeID($anonymous, User::ID_ANONYMOUS); } public function getDependencies(): array diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index f1e738d0..fa95e83d 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -42,6 +42,7 @@ final class UserRepository extends NamedDBElementRepository implements PasswordU /** * Returns the anonymous user. * The result is cached, so the database is only called once, after the anonymous user was found. + * @return User|null The user if it is existing, null if no one matched the criteria */ public function getAnonymousUser(): ?User { @@ -54,6 +55,30 @@ final class UserRepository extends NamedDBElementRepository implements PasswordU return $this->anonymous_user; } + /** + * Find a user by its username. + * @param string $username + * @return User|null + */ + public function findByUsername(string $username): ?User + { + if ($username === '') { + return null; + } + + $qb = $this->createQueryBuilder('u'); + $qb->select('u') + ->where('u.name = (:name)'); + + $qb->setParameter('name', $username); + + try { + return $qb->getQuery()->getOneOrNullResult(); + } catch (NonUniqueResultException) { + return null; + } + } + /** * Find a user by its name or its email. Useful for login or password reset purposes. * diff --git a/src/Services/UserSystem/PasswordResetManager.php b/src/Services/UserSystem/PasswordResetManager.php index 2349297b..31dbdf90 100644 --- a/src/Services/UserSystem/PasswordResetManager.php +++ b/src/Services/UserSystem/PasswordResetManager.php @@ -97,8 +97,7 @@ class PasswordResetManager { //Try to find the user $repo = $this->em->getRepository(User::class); - /** @var User|null $user */ - $user = $repo->findOneBy(['name' => $username]); + $user = $repo->findByUsername($username); //If no user matching the name, show an error message if (!$user instanceof User) { diff --git a/tests/Repository/UserRepositoryTest.php b/tests/Repository/UserRepositoryTest.php new file mode 100644 index 00000000..dea4a294 --- /dev/null +++ b/tests/Repository/UserRepositoryTest.php @@ -0,0 +1,86 @@ +. + */ + +namespace App\Tests\Repository; + +use App\Entity\UserSystem\User; +use App\Repository\UserRepository; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +class UserRepositoryTest extends WebTestCase +{ + + private $entityManager; + /** + * @var UserRepository + */ + private $repo; + + protected function setUp(): void + { + $kernel = self::bootKernel(); + + $this->entityManager = $kernel->getContainer() + ->get('doctrine') + ->getManager(); + + $this->repo = $this->entityManager->getRepository(User::class); + } + + + public function testGetAnonymousUser() + { + $user = $this->repo->getAnonymousUser(); + + $this->assertInstanceOf(User::class, $user); + $this->assertSame(User::ID_ANONYMOUS, $user->getId()); + $this->assertSame('anonymous', $user->getUsername()); + } + + public function testFindByEmailOrName() + { + //Test for email + $u = $this->repo->findByEmailOrName('user@invalid.invalid'); + $this->assertInstanceOf(User::class, $u); + $this->assertSame('user', $u->getUsername()); + + //Test for name + $u = $this->repo->findByEmailOrName('user'); + $this->assertInstanceOf(User::class, $u); + $this->assertSame('user', $u->getUsername()); + + //Check what happens for unknown user + $u = $this->repo->findByEmailOrName('unknown'); + $this->assertNull($u); + + } + + public function testFindByUsername() + { + $u = $this->repo->findByUsername('user'); + $this->assertInstanceOf(User::class, $u); + $this->assertSame('user', $u->getUsername()); + + //Check what happens for unknown user + $u = $this->repo->findByEmailOrName('unknown'); + $this->assertNull($u); + } +}