Passed
Push — b0.25.0 ( 49bfd1...335ecf )
by Sebastian
03:13
created

getAttemptsLeftWithSameIp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * Linna Framework.
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2018, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types=1);
11
12
namespace Linna\Authentication;
13
14
use Linna\Session\Session;
15
16
/**
17
 * Extend basic user authentication system with more security checks.
18
 */
19
class EnhancedAuthentication extends Authentication
20
{
21
    /**
22
     * @var int Max attempts for user name.
23
     */
24
    protected $maxAttemptsForUserName = 5;
25
26
    /**
27
     * @var int Max attempts for session id.
28
     */
29
    protected $maxAttemptsForSessionId = 10;
30
31
    /**
32
     * @var int Max attempts for ip address.
33
     */
34
    protected $maxAttemptsForIpAddress = 20;
35
36
    /**
37
     * @var int Max attempts for second.
38
     */
39
    protected $maxAttemptsForSecond = 40;
40
41
    /**
42
     * @var int Ban time in seconds.
43
     */
44
    protected $banTimeInSeconds = 900;
45
46
    /**
47
     * @var EnhancedAuthenticationMapperInterface Enhanced Authentication Mapper
48
     */
49
    private $enhancedAuthenticationMapper;
50
51
    /**
52
     * Class Constructor
53
     *
54
     * @param Session                               $session
55
     * @param Password                              $password
56
     * @param EnhancedAuthenticationMapperInterface $enhancedAuthenticationMapper
57
     * @param array                                 $options
58
     */
59 1
    public function __construct(
60
            Session $session,
61
            Password $password,
62
            EnhancedAuthenticationMapperInterface $enhancedAuthenticationMapper,
63
            array $options = []
64
        ) {
65 1
        parent::__construct($session, $password);
66
67 1
        $this->enhancedAuthenticationMapper = $enhancedAuthenticationMapper;
68
69
        [
70 1
            'maxAttemptsForUserName'  => $this->maxAttemptsForUserName,
71 1
            'maxAttemptsForSessionId' => $this->maxAttemptsForSessionId,
72 1
            'maxAttemptsForIpAddress' => $this->maxAttemptsForIpAddress,
73 1
            'maxAttemptsForSecond'    => $this->maxAttemptsForSecond,
74 1
            'banTimeInSeconds'        => $this->banTimeInSeconds
75 1
        ] = array_replace_recursive([
76 1
            'maxAttemptsForUserName'  => 5,
77
            'maxAttemptsForSessionId' => 10,
78
            'maxAttemptsForIpAddress' => 20,
79
            'maxAttemptsForSecond'    => 40,
80
            'banTimeInSeconds'        => 900
81 1
        ], $options);
82 1
    }
83
84
    /**
85
     * Return how many attemps are left for incorrect password.
86
     *
87
     * @param string $userName
88
     *
89
     * @return int Number of attempts with same user.
90
     */
91 28
    public function getAttemptsLeftWithSameUser(string $userName): int
92
    {
93 28
        $attemptsLeft = $this->maxAttemptsForUserName - $this->enhancedAuthenticationMapper->fetchAttemptsWithSameUser($userName, $this->banTimeInSeconds);
94
95
        //casting to int second param for avoid strange things with
96
        //max return value
97
        //http://php.net/manual/en/function.max.php
98 28
        return max(0, (int) $attemptsLeft);
99
    }
100
101
    /**
102
     * Return how many attemps are left for same session id.
103
     *
104
     * @param string $sessionId
105
     *
106
     * @return int Number of attempts with same session.
107
     */
108 28
    public function getAttemptsLeftWithSameSession(string $sessionId): int
109
    {
110 28
        $attemptsLeft = $this->maxAttemptsForSessionId - $this->enhancedAuthenticationMapper->fetchAttemptsWithSameSession($sessionId, $this->banTimeInSeconds);
111
112 28
        return max(0, (int) $attemptsLeft);
113
    }
114
115
    /**
116
     * Return how many attemps are left for same ip.
117
     *
118
     * @param string $ipAddress
119
     *
120
     * @return int Number of attempts with same ip.
121
     */
122 28
    public function getAttemptsLeftWithSameIp(string $ipAddress): int
123
    {
124 28
        $attemptsLeft = $this->maxAttemptsForIpAddress - $this->enhancedAuthenticationMapper->fetchAttemptsWithSameIp($ipAddress, $this->banTimeInSeconds);
125
126 28
        return max(0, (int) $attemptsLeft);
127
    }
128
129
    /**
130
     * Check if an user is banned from do login.
131
     *
132
     * @param string $userName
133
     *
134
     * @return bool
135
     */
136 28
    public function isUserBanned(string $userName): bool
137
    {
138 28
        return !$this->getAttemptsLeftWithSameUser($userName);
139
    }
140
141
    /**
142
     * Check if a session id is banned from do login.
143
     *
144
     * @param string $sessionId
145
     *
146
     * @return bool
147
     */
148 28
    public function isSessionBanned(string $sessionId): bool
149
    {
150 28
        return !$this->getAttemptsLeftWithSameSession($sessionId);
151
    }
152
153
    /**
154
     * Check if an ip address is banned from do login.
155
     *
156
     * @param string $ipAddress
157
     *
158
     * @return bool
159
     */
160 28
    public function isIpBanned(string $ipAddress): bool
161
    {
162 28
        return !$this->getAttemptsLeftWithSameIp($ipAddress);
163
    }
164
}
165