Issues (21)

src/PdoNewCredentialsValidator.php (2 issues)

1
<?php
2
namespace Germania\UserProfiles;
3
4
use Psr\Log\LoggerInterface;
5
use Psr\Log\NullLogger;
6
use Ramsey\Uuid\Uuid;
7
use Ramsey\Uuid\UuidFactory;
8
9
/**
10
 * This Callable checks if given username and password match a stored login name and password combination,
11
 * using a custom verifier function.
12
 *
13
 * Example:
14
 *
15
 *     <?php
16
 *     use Germania\UserProfiles\PdoNewCredentialsValidator;
17
 *
18
 *     $pdo      = new PDO( ... );
19
 *     $verifier = function() { return false; };
20
 *     $logger   = new Monolog();
21
 *     $table    = 'users';
22
 *
23
 *     $checker = new PdoNewCredentialsValidator( $pdo, $verifier, $logger, $table);
24
 *     $data = $checker( '[email protected]', 'take_this_secret' );
25
 *     ?>
26
 *
27
 * @author  Carsten Witt <[email protected]>
28
 */
29
class PdoNewCredentialsValidator
30
{
31
32
    /**
33
     * Database table
34
     * @var string
35
     */
36
    public $table = 'users';
37
38
    /**
39
     * @var PDOStatement
0 ignored issues
show
The type Germania\UserProfiles\PDOStatement was not found. Did you mean PDOStatement? If so, make sure to prefix the type with \.
Loading history...
40
     */
41
    public $stmt;
42
43
    /**
44
     * @var Callable
45
     */
46
    public $password_verifier;
47
48
    /**
49
     * @var LoggerInterface
50
     */
51
    public $logger;
52
53
    /**
54
     * @var UuidFactory
55
     */
56
    public $uuid_factory;
57
58
59
    /**
60
     * @param PDO             $pdo                PDO instance
61
     * @param Callable        $password_verifier  Callable password verifier that accepts password and password hash
62
     * @param LoggerInterface $logger             Optional: PSR-3 Logger
63
     * @param string          $table              Optional: Database table name
64
     */
65
    public function __construct( \PDO $pdo, Callable $password_verifier, LoggerInterface $logger = null, $table = null)
66
    {
67
        $this->password_verifier = $password_verifier;
68
        $this->logger            = $logger ?: new NullLogger;
69
        $this->table             = $table  ?: $this->table;
70
        $this->uuid_factory      = new UuidFactory;
71
72
73
        // Prepare business
74
        $sql = "SELECT
75
        id,
76
        LOWER(HEX(uuid)) as uuid,
77
        api_key,
78
        password
79
        FROM {$this->table}
80
        WHERE user_login_name = :login_name
81
        LIMIT 1";
82
83
        // Store for later use
84
        $this->stmt = $pdo->prepare( $sql );
0 ignored issues
show
Documentation Bug introduced by
It seems like $pdo->prepare($sql) of type PDOStatement or boolean is incompatible with the declared type Germania\UserProfiles\PDOStatement of property $stmt.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
85
86
    }
87
88
89
90
    /**
91
     * @param  string $login_name
92
     * @param  string $password
93
     *
94
     * @return mixed  Array with User's ID, UUID, and API key, or FALSE on wrong credentials
95
     */
96
    public function __invoke( $login_name, $password )
97
    {
98
99
        // Perform
100
        $this->stmt->execute([
101
            'login_name' => $login_name
102
        ]);
103
104
105
        // If user not found...
106
        $found_user = $this->stmt->fetch( \PDO::FETCH_ASSOC );
107
        if (!$found_user):
108
            $this->logger->warning("User login name not found", [
109
                'user_name' => $login_name
110
            ]);
111
            return false;
112
        endif;
113
114
115
        // If password is wrong...
116
        $verifier = $this->password_verifier;
117
        if(!$verifier( $password, $found_user['password'])) :
118
119
            $this->logger->warning("Wrong password", [
120
                'user_name' => $login_name
121
            ]);
122
            return false;
123
        endif;
124
125
        // Return found user data
126
        $uuid_factory = $this->uuid_factory;
127
        $uuid = $uuid_factory->fromString( $found_user['uuid'] );
128
129
        return [
130
            'id'      => $found_user['id'],
131
            'uuid'    => $uuid,
132
            'api_key' => $found_user['api_key']
133
        ];
134
135
    }
136
137
138
139
}
140