• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarlepp / symfony-flex-backend / #6272

12 Jul 2026 07:50PM UTC coverage: 99.68% (-0.2%) from 99.876%
#6272

Pull #3336

php-coveralls

web-flow
Merge 764e37d64 into db63c2324
Pull Request #3336: Chore(deps) - Dependency update

2490 of 2498 relevant lines covered (99.68%)

87.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.67
/src/EventSubscriber/LockedUserSubscriber.php
1
<?php
2
declare(strict_types = 1);
3

4
/**
5
 * /src/EventSubscriber/LockedUserSubscriber.php
6
 */
7

8
namespace App\EventSubscriber;
9

10
use App\Entity\LogLoginFailure;
11
use App\Entity\User;
12
use App\Repository\UserRepository;
13
use App\Resource\LogLoginFailureResource;
14
use App\Security\SecurityUser;
15
use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationFailureEvent;
16
use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationSuccessEvent;
17
use Lexik\Bundle\JWTAuthenticationBundle\Events;
18
use Override;
19
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\HttpFoundation\RequestStack;
22
use Symfony\Component\Security\Core\Exception\LockedException;
23
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
24
use Throwable;
25
use function assert;
26
use function count;
27
use function is_string;
28

29
class LockedUserSubscriber implements EventSubscriberInterface
30
{
31
    public function __construct(
32
        private readonly UserRepository $userRepository,
33
        private readonly LogLoginFailureResource $logLoginFailureResource,
34
        private readonly RequestStack $requestStack,
35
    ) {
36
    }
22✔
37

38
    /**
39
     * {@inheritDoc}
40
     */
41
    #[Override]
42
    public static function getSubscribedEvents(): array
43
    {
44
        return [
1✔
45
            AuthenticationSuccessEvent::class => [
1✔
46
                'onAuthenticationSuccess',
1✔
47
                128,
1✔
48
            ],
1✔
49
            Events::AUTHENTICATION_SUCCESS => [
1✔
50
                'onAuthenticationSuccess',
1✔
51
                128,
1✔
52
            ],
1✔
53
            AuthenticationFailureEvent::class => 'onAuthenticationFailure',
1✔
54
            Events::AUTHENTICATION_FAILURE => 'onAuthenticationFailure',
1✔
55
        ];
1✔
56
    }
57

58
    /**
59
     * @throws Throwable
60
     */
61
    public function onAuthenticationSuccess(AuthenticationSuccessEvent $event): void
62
    {
63
        $user = $this->getUser($event->getUser()) ?? throw new UnsupportedUserException('Unsupported user.');
18✔
64

65
        if (count($user->getLogsLoginFailure()) > 10) {
17✔
66
            throw new LockedException('Locked account.');
2✔
67
        }
68

69
        $this->logLoginFailureResource->reset($user);
15✔
70
    }
71

72
    /**
73
     * @throws Throwable
74
     */
75
    public function onAuthenticationFailure(): void
76
    {
77
        $request = $this->requestStack->getCurrentRequest();
5✔
78

79
        assert($request instanceof Request);
×
80

81
        $user = $this->getUser(
5✔
82
            (string)($request->query->get('username') ?? $request->request->get('username', ''))
5✔
83
        );
5✔
84

85
        if ($user !== null) {
5✔
86
            $this->logLoginFailureResource->save(new LogLoginFailure($user), true);
3✔
87
        }
88
    }
89

90
    /**
91
     * @throws Throwable
92
     */
93
    private function getUser(string|object $user): ?User
94
    {
95
        return match (true) {
96
            is_string($user) => $this->userRepository->loadUserByIdentifier($user, false),
22✔
97
            $user instanceof SecurityUser => $this->userRepository->loadUserByIdentifier(
18✔
98
                $user->getUserIdentifier(),
18✔
99
                true,
18✔
100
            ),
18✔
101
            default => null,
22✔
102
        };
103
    }
104
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc