UserRepository   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Test Coverage

Coverage 91.43%

Importance

Changes 0
Metric Value
wmc 14
eloc 30
dl 0
loc 90
ccs 32
cts 35
cp 0.9143
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getAccessibleSubQuery() 0 9 2
A getOneById() 0 5 1
A getOneByEmail() 0 5 1
A getOrCreate() 0 10 2
B getOneByEmailPassword() 0 30 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Repository;
6
7
use Application\Model\User;
8
use Ecodev\Felix\Repository\LimitedAccessSubQuery;
9
10
/**
11
 * @extends AbstractRepository<User>
12
 */
13
class UserRepository extends AbstractRepository implements LimitedAccessSubQuery
14
{
15
    /**
16
     * Returns pure SQL to get ID of all objects that are accessible to given user.
17
     *
18
     * @param null|User $user
19
     */
20 12
    public function getAccessibleSubQuery(?\Ecodev\Felix\Model\User $user): string
21
    {
22 12
        if (!$user) {
23 2
            $facilitator = $this->getEntityManager()->getConnection()->quote(User::ROLE_FACILITATOR);
24
25 2
            return 'SELECT id FROM user WHERE role = ' . $facilitator;
26
        }
27
28 10
        return '';
29
    }
30
31
    /**
32
     * Returns the user authenticated by its email and password.
33
     */
34 2
    public function getOneByEmailPassword(string $email, string $password): ?User
35
    {
36
        /** @var null|User $user */
37 2
        $user = $this->getOneByEmail($email);
38
39 2
        if (!$user) {
40 1
            return null;
41
        }
42
43 2
        $hashFromDb = $user->getPassword();
44 2
        $isMd5 = mb_strlen($hashFromDb) === 32 && ctype_xdigit($hashFromDb);
45
46 2
        $possibleMd5 = [
47 2
            md5($password), // normal md5 for our test data
48 2
            md5('oQqnnn8sVBZzveU2zWCqdcu8N9JVE3GXFq6kS0i1ZyS3FkFoPZAN3GCA' . $password), // From PrestaShop `\ToolsCore::encrypt()` with hardcoded _COOKIE_KEY_ value
49 2
        ];
50
51
        // If we found a user and he has a correct MD5 or correct new hash, then return the user
52 2
        if (($isMd5 && in_array($hashFromDb, $possibleMd5, true)) || password_verify($password, $hashFromDb)) {
53
            // Update the hash in DB, if we are still MD5, or if PHP default options changed
54 2
            if ($isMd5 || password_needs_rehash($hashFromDb, PASSWORD_DEFAULT)) {
55 2
                $user->setPassword($password);
56
            }
57 2
            $user->revokeToken();
58 2
            $this->getEntityManager()->flush();
59
60 2
            return $user;
61
        }
62
63 1
        return null;
64
    }
65
66
    /**
67
     * Unsecured way to get a user from its ID.
68
     *
69
     * This should only be used in tests or controlled environment.
70
     */
71 2
    public function getOneById(int $id): ?User
72
    {
73 2
        $user = $this->getAclFilter()->runWithoutAcl(fn () => $this->findOneById($id));
74
75 2
        return $user;
76
    }
77
78
    /**
79
     * Unsecured way to get a user from its email.
80
     *
81
     * This should only be used in tests or controlled environment.
82
     */
83 63
    public function getOneByEmail(?string $email): ?User
84
    {
85 63
        $user = $this->getAclFilter()->runWithoutAcl(fn () => $this->findOneByEmail($email));
86
87 63
        return $user;
88
    }
89
90
    /**
91
     * Get or create the user for the given email.
92
     */
93 1
    public function getOrCreate(string $email): User
94
    {
95 1
        $user = $this->getOneByEmail($email);
96 1
        if (!$user) {
97
            $user = new User();
98
            $this->getEntityManager()->persist($user);
99
            $user->setEmail($email);
100
        }
101
102 1
        return $user;
103
    }
104
}
105