Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
AuthRequestRepository
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 3
110
0.00% covered (danger)
0.00%
0 / 1
 addAuthRequest
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 numRemainingAttempts
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
20
 canValidateAccessToken
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace Olz\Repository;
4
5use Olz\Entity\AuthRequest;
6use Olz\Repository\Common\OlzRepository;
7
8/**
9 * @extends OlzRepository<AuthRequest>
10 */
11class AuthRequestRepository extends OlzRepository {
12    protected string $auth_request_class = AuthRequest::class;
13
14    public const NUM_TRIES = 8;
15    public const TRIES_RESET_INTERVAL = '+8 hour'; // Reset after 8h
16
17    public function addAuthRequest(
18        string $ip_address,
19        string $action,
20        string $username,
21        ?\DateTime $timestamp = null,
22    ): void {
23        if ($timestamp === null) {
24            $timestamp = new \DateTime();
25        }
26        $auth_request = new AuthRequest();
27        $auth_request->setIpAddress($ip_address);
28        $auth_request->setAction($action);
29        $auth_request->setTimestamp($timestamp);
30        $auth_request->setUsername($username);
31        $this->getEntityManager()->persist($auth_request);
32        $this->getEntityManager()->flush();
33    }
34
35    public function numRemainingAttempts(string $ip_address, ?\DateTime $timestamp = null): int {
36        $db = $this->dbUtils()->getDb();
37
38        $tries_reset_interval = \DateInterval::createFromDateString(self::TRIES_RESET_INTERVAL);
39        if ($timestamp === null) {
40            $timestamp = new \DateTime();
41        }
42        $sanitized_ip_address = $db->escape_string($ip_address);
43        $min_timestamp = $timestamp->sub($tries_reset_interval);
44        $sanitized_min_timestamp = $min_timestamp->format('Y-m-d H:i:s');
45        $dql = "
46            SELECT ar 
47            FROM {$this->auth_request_class} ar 
48            WHERE 
49                ar.ip_address='{$sanitized_ip_address}
50                AND ar.timestamp>'{$sanitized_min_timestamp}'
51                AND ar.action IN ('AUTHENTICATED', 'BLOCKED', 'INVALID_CREDENTIALS')
52            ORDER BY ar.timestamp DESC";
53        $query = $this->getEntityManager()->createQuery($dql);
54        $query->setMaxResults(self::NUM_TRIES);
55        $auth_requests = $query->getResult();
56        $num_unsuccessful_auth_requests = 0;
57        foreach ($auth_requests as $auth_request) {
58            $action = $auth_request->getAction();
59            if ($action === 'AUTHENTICATED') {
60                break;
61            }
62            $num_unsuccessful_auth_requests++;
63        }
64        return self::NUM_TRIES - $num_unsuccessful_auth_requests;
65    }
66
67    public function canValidateAccessToken(string $ip_address, ?\DateTime $timestamp = null): bool {
68        $db = $this->dbUtils()->getDb();
69
70        $tries_reset_interval = \DateInterval::createFromDateString(self::TRIES_RESET_INTERVAL);
71        if ($timestamp === null) {
72            $timestamp = new \DateTime();
73        }
74        $sanitized_ip_address = $db->escape_string($ip_address);
75        $min_timestamp = $timestamp->sub($tries_reset_interval);
76        $sanitized_min_timestamp = $min_timestamp->format('Y-m-d H:i:s');
77        $dql = "
78            SELECT ar 
79            FROM {$this->auth_request_class} ar 
80            WHERE 
81                ar.ip_address='{$sanitized_ip_address}
82                AND ar.timestamp>'{$sanitized_min_timestamp}'
83                AND ar.action IN ('TOKEN_VALIDATED', 'TOKEN_BLOCKED', 'INVALID_TOKEN', 'EXPIRED_TOKEN')
84            ORDER BY ar.timestamp DESC";
85        $query = $this->getEntityManager()->createQuery($dql);
86        $query->setMaxResults(self::NUM_TRIES);
87        $auth_requests = $query->getResult();
88        $num_unsuccessful_auth_requests = 0;
89        foreach ($auth_requests as $auth_request) {
90            $action = $auth_request->getAction();
91            if ($action === 'TOKEN_VALIDATED') {
92                break;
93            }
94            $num_unsuccessful_auth_requests++;
95        }
96        return $num_unsuccessful_auth_requests < self::NUM_TRIES;
97    }
98}