Completed
Pull Request — 2.x (#80)
by
unknown
02:00
created

PdoAdapter::getVerifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
nc 1
cc 1
eloc 2
nop 0
crap 1
1
<?php
2
/**
3
 *
4
 * This file is part of Aura for PHP.
5
 *
6
 * @license http://opensource.org/licenses/bsd-license.php BSD
7
 *
8
 */
9
namespace Aura\Auth\Adapter;
10
11
use PDO;
12
use Aura\Auth\Verifier\VerifierInterface;
13
use Aura\Auth\Exception;
14
15
/**
16
 *
17
 * Authenticate against an SQL database table via PDO.
18
 *
19
 * @package Aura.Auth
20
 *
21
 */
22
class PdoAdapter extends AbstractAdapter
23
{
24
    /**
25
     *
26
     * A PDO connection object.
27
     *
28
     * @var PDO
29
     *
30
     */
31
    protected $pdo;
32
33
    /**
34
     *
35
     * Columns to be selected.
36
     *
37
     * @param array
38
     *
39
     */
40
    protected $cols = array();
41
42
    /**
43
     *
44
     * Select FROM this table; add JOIN specifications here as needed.
45
     *
46
     * @var string
47
     *
48
     */
49
    protected $from;
50
51
    /**
52
     *
53
     * Added WHERE conditions for the select.
54
     *
55
     * @var string
56
     *
57
     */
58
    protected $where;
59
60
    /**
61
     *
62
     * A verifier for passwords.
63
     *
64
     * @var VerifierInterface
65
     *
66
     */
67
    protected $verifier;
68
69
    /**
70
     *
71
     * Constructor
72
     *
73
     * @param \PDO $pdo A PDO connection.
74
     *
75
     * @param VerifierInterface $verifier A password verifier.
76
     *
77
     * @param array $cols The columns to be selected.
78
     *
79
     * @param string $from The table (and joins) to select from.
80
     *
81
     * @param string $where The where clause to use.
82
     *
83
     */
84 12
    public function __construct(
85
        PDO $pdo,
86
        VerifierInterface $verifier,
87
        array $cols,
88
        $from,
89
        $where = null
90
    ) {
91 12
        $this->pdo = $pdo;
92 12
        $this->verifier = $verifier;
93 12
        $this->setCols($cols);
94 12
        $this->from = $from;
95 12
        $this->where = $where;
96 12
    }
97
98
    /**
99
     *
100
     * Set the $cols property.
101
     *
102
     * @param array $cols The columns to select.
103
     *
104
     * @return null
105
     *
106
     * @throws Exception\UsernameColumnNotSpecified
107
     *
108
     * @throws Exception\PasswordColumnNotSpecified
109
     *
110
     */
111 12
    protected function setCols($cols)
112
    {
113 12
        if (! isset($cols[0]) || trim($cols[0] == '')) {
114 1
            throw new Exception\UsernameColumnNotSpecified;
115
        }
116 12
        if (! isset($cols[1]) || trim($cols[1] == '')) {
117 1
            throw new Exception\PasswordColumnNotSpecified;
118
        }
119 12
        $this->cols = $cols;
120 12
    }
121
122
    /**
123
     *
124
     * Returns the password verifier.
125
     *
126
     * @return VerifierInterface
127
     *
128
     */
129 2
    public function getVerifier()
130
    {
131 2
        return $this->verifier;
132
    }
133
134
    /**
135
     *
136
     * Verifies the username/password credentials.
137
     *
138
     * @param array $input An array of credential data, including any data to
139
     * bind to the query.
140
     *
141
     * @return array An array of login data.
142
     *
143
     */
144 7
    public function login(array $input)
145
    {
146 7
        $this->checkInput($input);
147 5
        $data = $this->fetchRow($input);
148 3
        $this->verify($input, $data);
149 2
        $name = $data['username'];
150 2
        unset($data['username']);
151 2
        unset($data['password']);
152 2
        return array($name, $data);
153
    }
154
155
    /**
156
     *
157
     * Fetches a single matching row from the database.
158
     *
159
     * @param array $input The user input.
160
     *
161
     * @return array The found row.
162
     *
163
     * @throws Exception\UsernameNotFound when no row is found.
164
     *
165
     * @throws Exception\MultipleMatches where more than one row is found.
166
     *
167
     */
168 5
    protected function fetchRow($input)
169
    {
170 5
        $stm = $this->buildSelect();
171 5
        $rows = $this->fetchRows($stm, $input);
172
173 5
        if (count($rows) < 1) {
174 1
            throw new Exception\UsernameNotFound;
175
        }
176
177 4
        if (count($rows) > 1) {
178 1
            throw new Exception\MultipleMatches;
179
        }
180
181 3
        return $rows[0];
182
    }
183
184
    /**
185
     *
186
     * Fetches all matching rows from the database.
187
     *
188
     * @param string $stm The SQL statement to execute.
189
     *
190
     * @param array $bind Values to bind to the query.
191
     *
192
     * @return array
193
     *
194
     */
195 5
    protected function fetchRows($stm, $bind)
196
    {
197 5
        $sth = $this->pdo->prepare($stm);
198 5
        unset($bind['password']);
199 5
        $sth->execute($bind);
200 5
        return $sth->fetchAll(PDO::FETCH_ASSOC);
201
    }
202
203
    /**
204
     *
205
     * Builds the SQL statement for finding the user data.
206
     *
207
     * @return string
208
     *
209
     */
210 5
    protected function buildSelect()
211
    {
212 5
        $cols = $this->buildSelectCols();
213 5
        $from = $this->buildSelectFrom();
214 5
        $where = $this->buildSelectWhere();
215 5
        return "SELECT {$cols} FROM {$from} WHERE {$where}";
216
    }
217
218
    /**
219
     *
220
     * Builds the SELECT column list.
221
     *
222
     * @return string
223
     *
224
     */
225 5
    protected function buildSelectCols()
226
    {
227 5
        $cols = $this->cols;
228 5
        $cols[0] .= ' AS username';
229 5
        $cols[1] .= ' AS password';
230 5
        return implode(', ', $cols);
231
    }
232
233
    /**
234
     *
235
     * Builds the FROM clause.
236
     *
237
     * @return string
238
     *
239
     */
240 5
    protected function buildSelectFrom()
241
    {
242 5
        return $this->from;
243
    }
244
245
    /**
246
     *
247
     * Builds the WHERE clause.
248
     *
249
     * @return string
250
     *
251
     */
252 5
    protected function buildSelectWhere()
253
    {
254 5
        $where = $this->cols[0] . " = :username";
255 5
        if ($this->where) {
256 1
            $where .= " AND ({$this->where})";
257 1
        }
258 5
        return $where;
259
    }
260
261
    /**
262
     *
263
     * Verifies the password.
264
     *
265
     * @param array $input The user input array.
266
     *
267
     * @param array $data The data from the database.
268
     *
269
     * @return bool
270
     *
271
     * @throws Exception\PasswordIncorrect
272
     *
273
     */
274 3
    protected function verify($input, $data)
275
    {
276 3
        $verified = $this->verifier->verify(
277 3
            $input['password'],
278 3
            $data['password'],
279
            $data
280 3
        );
281
282 3
        if (! $verified) {
283 1
            throw new Exception\PasswordIncorrect;
284
        }
285
286 2
        return true;
287
    }
288
}
289