Completed
Push — master ( 055b70...427a37 )
by Artem
03:41
created

UserLockout::onSuccess()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 2
nop 1
crap 3
1
<?php
2
3
//----------------------------------------------------------------------
4
//
5
//  Copyright (C) 2017 Artem Rodygin
6
//
7
//  You should have received a copy of the MIT License along with
8
//  this file. If not, see <http://opensource.org/licenses/MIT>.
9
//
10
//----------------------------------------------------------------------
11
12
namespace Pignus\EventListener;
13
14
use Doctrine\Common\Persistence\ObjectManager;
15
use Pignus\Model\LockAccountTrait;
16
use Psr\Log\LoggerInterface;
17
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18
use Symfony\Component\Security\Core\AuthenticationEvents;
19
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
20
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
21
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
22
use Symfony\Component\Security\Core\User\UserInterface;
23
use Symfony\Component\Security\Core\User\UserProviderInterface;
24
25
/**
26
 * Locks/unlocks user in accordance with the authentication attempt.
27
 */
28
class UserLockout implements EventSubscriberInterface
29
{
30
    protected $logger;
31
    protected $manager;
32
    protected $provider;
33
    protected $auth_failures;
34
    protected $lock_duration;
35
36
    /**
37
     * Dependency Injection constructor.
38
     *
39
     * @param LoggerInterface       $logger
40
     * @param ObjectManager         $manager
41
     * @param UserProviderInterface $provider
42
     * @param int                   $auth_failures
43
     * @param int                   $lock_duration
44
     */
45 5
    public function __construct(
46
        LoggerInterface       $logger,
47
        ObjectManager         $manager,
48
        UserProviderInterface $provider,
49
        int                   $auth_failures = null,
50
        int                   $lock_duration = null)
51
    {
52 5
        $this->logger        = $logger;
53 5
        $this->manager       = $manager;
54 5
        $this->provider      = $provider;
55 5
        $this->auth_failures = $auth_failures;
56 5
        $this->lock_duration = $lock_duration;
57 5
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 1
    public static function getSubscribedEvents()
63
    {
64
        return [
65 1
            AuthenticationEvents::AUTHENTICATION_SUCCESS => 'onSuccess',
66 1
            AuthenticationEvents::AUTHENTICATION_FAILURE => 'onFailure',
67
        ];
68
    }
69
70
    /**
71
     * Callback for successful authentication event.
72
     *
73
     * @param AuthenticationEvent $event
74
     */
75 1
    public function onSuccess(AuthenticationEvent $event)
76
    {
77 1
        $token = $event->getAuthenticationToken();
78
79
        /** @var LockAccountTrait $user */
80 1
        $user = $token->getUser();
81
82 1
        if ($user instanceof UserInterface && in_array(LockAccountTrait::class, class_uses($user), true)) {
83
84 1
            $this->logger->info('Authentication success', [$user->getUsername()]);
85
86 1
            $user->unlockAccount();
0 ignored issues
show
Bug introduced by
The method unlockAccount() does not seem to exist on object<Symfony\Component...ore\User\UserInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
87
88 1
            $this->manager->persist($user);
89 1
            $this->manager->flush();
90
        }
91 1
    }
92
93
    /**
94
     * Callback for failed authentication event.
95
     *
96
     * @param AuthenticationFailureEvent $event
97
     */
98 4
    public function onFailure(AuthenticationFailureEvent $event)
99
    {
100 4
        $token = $event->getAuthenticationToken();
101
102 4
        $credentials = $token->getCredentials();
103 4
        $username    = $token->getUsername() ?: ($credentials['username'] ?? null);
104
105 4
        if ($username && $this->auth_failures !== null) {
106
107
            try {
108
                /** @var LockAccountTrait $user */
109 3
                $user = $this->provider->loadUserByUsername($username);
110
111 2
                if ($user instanceof UserInterface && in_array(LockAccountTrait::class, class_uses($user), true)) {
112
113 2
                    $this->logger->info('Authentication failure', [$username]);
114
115 2
                    if ($user->incAuthFailures() >= $this->auth_failures) {
0 ignored issues
show
Bug introduced by
The method incAuthFailures() does not seem to exist on object<Symfony\Component...ore\User\UserInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
116
117 2
                        if ($this->lock_duration === null) {
118 1
                            $user->lockAccount();
0 ignored issues
show
Bug introduced by
The method lockAccount() does not seem to exist on object<Symfony\Component...ore\User\UserInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
119
                        }
120
                        else {
121 1
                            $interval = sprintf('PT%dM', $this->lock_duration);
122 1
                            $user->lockAccount(date_create()->add(new \DateInterval($interval)));
0 ignored issues
show
Bug introduced by
The method lockAccount() does not seem to exist on object<Symfony\Component...ore\User\UserInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
123
                        }
124
                    }
125
126 2
                    $this->manager->persist($user);
127 2
                    $this->manager->flush();
128
                }
129
            }
130 1
            catch (UsernameNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
131
            }
132
        }
133 4
    }
134
}
135