|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Copyright (C) 2016 SURFnet. |
|
4
|
|
|
* |
|
5
|
|
|
* This program is free software: you can redistribute it and/or modify |
|
6
|
|
|
* it under the terms of the GNU Affero General Public License as |
|
7
|
|
|
* published by the Free Software Foundation, either version 3 of the |
|
8
|
|
|
* License, or (at your option) any later version. |
|
9
|
|
|
* |
|
10
|
|
|
* This program is distributed in the hope that it will be useful, |
|
11
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13
|
|
|
* GNU Affero General Public License for more details. |
|
14
|
|
|
* |
|
15
|
|
|
* You should have received a copy of the GNU Affero General Public License |
|
16
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
17
|
|
|
*/ |
|
18
|
|
|
|
|
19
|
|
|
namespace SURFnet\VPN\Server; |
|
20
|
|
|
|
|
21
|
|
|
use DateTime; |
|
22
|
|
|
use fkooman\OAuth\Client\AccessToken; |
|
23
|
|
|
use fkooman\OAuth\Client\TokenStorageInterface; |
|
24
|
|
|
use PDO; |
|
25
|
|
|
use PDOException; |
|
26
|
|
|
|
|
27
|
|
|
class Storage implements TokenStorageInterface |
|
28
|
|
|
{ |
|
29
|
|
|
/** @var \PDO */ |
|
30
|
|
|
private $db; |
|
31
|
|
|
|
|
32
|
|
|
/** @var \DateTime */ |
|
33
|
|
|
private $dateTime; |
|
34
|
|
|
|
|
35
|
|
|
public function __construct(PDO $db, DateTime $dateTime) |
|
36
|
|
|
{ |
|
37
|
|
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
|
38
|
|
|
if ('sqlite' === $db->getAttribute(PDO::ATTR_DRIVER_NAME)) { |
|
39
|
|
|
$db->query('PRAGMA foreign_keys = ON'); |
|
40
|
|
|
} |
|
41
|
|
|
|
|
42
|
|
|
$this->db = $db; |
|
43
|
|
|
$this->dateTime = $dateTime; |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* @return array |
|
48
|
|
|
*/ |
|
49
|
|
|
public function getUsers() |
|
50
|
|
|
{ |
|
51
|
|
|
$stmt = $this->db->prepare( |
|
52
|
|
|
<<< 'SQL' |
|
53
|
|
|
SELECT |
|
54
|
|
|
user_id, |
|
55
|
|
|
date_time, |
|
56
|
|
|
totp_secret, |
|
57
|
|
|
yubi_key_id, |
|
58
|
|
|
is_disabled |
|
59
|
|
|
FROM |
|
60
|
|
|
users |
|
61
|
|
|
SQL |
|
62
|
|
|
); |
|
63
|
|
|
$stmt->execute(); |
|
64
|
|
|
|
|
65
|
|
|
$userList = []; |
|
66
|
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { |
|
67
|
|
|
$userList[] = [ |
|
68
|
|
|
'user_id' => $row['user_id'], |
|
69
|
|
|
'is_disabled' => (bool) $row['is_disabled'], |
|
70
|
|
|
'has_yubi_key_id' => !is_null($row['yubi_key_id']), |
|
71
|
|
|
'has_totp_secret' => !is_null($row['totp_secret']), |
|
72
|
|
|
]; |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
return $userList; |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* @return array|false |
|
80
|
|
|
*/ |
|
81
|
|
View Code Duplication |
public function getUserCertificateInfo($commonName) |
|
|
|
|
|
|
82
|
|
|
{ |
|
83
|
|
|
$stmt = $this->db->prepare( |
|
84
|
|
|
<<< 'SQL' |
|
85
|
|
|
SELECT |
|
86
|
|
|
u.user_id AS user_id, |
|
87
|
|
|
u.is_disabled AS user_is_disabled, |
|
88
|
|
|
c.display_name AS display_name, |
|
89
|
|
|
c.is_disabled AS certificate_is_disabled |
|
90
|
|
|
FROM |
|
91
|
|
|
users u, certificates c |
|
92
|
|
|
WHERE |
|
93
|
|
|
u.user_id = c.user_id AND |
|
94
|
|
|
c.common_name = :common_name |
|
95
|
|
|
SQL |
|
96
|
|
|
); |
|
97
|
|
|
|
|
98
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
99
|
|
|
$stmt->execute(); |
|
100
|
|
|
|
|
101
|
|
|
return $stmt->fetch(PDO::FETCH_ASSOC); |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
/** |
|
105
|
|
|
* @return string|null |
|
106
|
|
|
*/ |
|
107
|
|
View Code Duplication |
public function getVootToken($userId) |
|
|
|
|
|
|
108
|
|
|
{ |
|
109
|
|
|
$this->addUser($userId); |
|
110
|
|
|
$stmt = $this->db->prepare( |
|
111
|
|
|
<<< 'SQL' |
|
112
|
|
|
SELECT |
|
113
|
|
|
voot_token |
|
114
|
|
|
FROM |
|
115
|
|
|
users |
|
116
|
|
|
WHERE |
|
117
|
|
|
user_id = :user_id |
|
118
|
|
|
SQL |
|
119
|
|
|
); |
|
120
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
121
|
|
|
$stmt->execute(); |
|
122
|
|
|
|
|
123
|
|
|
return $stmt->fetchColumn(); |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
View Code Duplication |
public function setVootToken($userId, AccessToken $vootToken) |
|
|
|
|
|
|
127
|
|
|
{ |
|
128
|
|
|
$this->addUser($userId); |
|
129
|
|
|
$stmt = $this->db->prepare( |
|
130
|
|
|
<<< 'SQL' |
|
131
|
|
|
UPDATE |
|
132
|
|
|
users |
|
133
|
|
|
SET |
|
134
|
|
|
voot_token = :voot_token |
|
135
|
|
|
WHERE |
|
136
|
|
|
user_id = :user_id |
|
137
|
|
|
SQL |
|
138
|
|
|
); |
|
139
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
140
|
|
|
$stmt->bindValue(':voot_token', $vootToken->toStorage(), PDO::PARAM_STR); |
|
141
|
|
|
|
|
142
|
|
|
$stmt->execute(); |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* @return bool |
|
147
|
|
|
*/ |
|
148
|
|
View Code Duplication |
public function hasVootToken($userId) |
|
|
|
|
|
|
149
|
|
|
{ |
|
150
|
|
|
$this->addUser($userId); |
|
151
|
|
|
$stmt = $this->db->prepare( |
|
152
|
|
|
<<< 'SQL' |
|
153
|
|
|
SELECT |
|
154
|
|
|
voot_token |
|
155
|
|
|
FROM |
|
156
|
|
|
users |
|
157
|
|
|
WHERE |
|
158
|
|
|
user_id = :user_id |
|
159
|
|
|
SQL |
|
160
|
|
|
); |
|
161
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
162
|
|
|
$stmt->execute(); |
|
163
|
|
|
|
|
164
|
|
|
return !is_null($stmt->fetchColumn()); |
|
165
|
|
|
} |
|
166
|
|
|
|
|
167
|
|
|
public function deleteVootToken($userId) |
|
168
|
|
|
{ |
|
169
|
|
|
$this->addUser($userId); |
|
170
|
|
|
$stmt = $this->db->prepare( |
|
171
|
|
|
<<< 'SQL' |
|
172
|
|
|
UPDATE |
|
173
|
|
|
users |
|
174
|
|
|
SET |
|
175
|
|
|
voot_token = NULL |
|
176
|
|
|
WHERE |
|
177
|
|
|
user_id = :user_id |
|
178
|
|
|
SQL |
|
179
|
|
|
); |
|
180
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
181
|
|
|
|
|
182
|
|
|
$stmt->execute(); |
|
183
|
|
|
} |
|
184
|
|
|
|
|
185
|
|
|
/** |
|
186
|
|
|
* @return bool |
|
187
|
|
|
*/ |
|
188
|
|
View Code Duplication |
public function hasTotpSecret($userId) |
|
|
|
|
|
|
189
|
|
|
{ |
|
190
|
|
|
$this->addUser($userId); |
|
191
|
|
|
$stmt = $this->db->prepare( |
|
192
|
|
|
<<< 'SQL' |
|
193
|
|
|
SELECT |
|
194
|
|
|
totp_secret |
|
195
|
|
|
FROM |
|
196
|
|
|
users |
|
197
|
|
|
WHERE |
|
198
|
|
|
user_id = :user_id |
|
199
|
|
|
SQL |
|
200
|
|
|
); |
|
201
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
202
|
|
|
$stmt->execute(); |
|
203
|
|
|
|
|
204
|
|
|
return !is_null($stmt->fetchColumn()); |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
/** |
|
208
|
|
|
* @return string|null |
|
209
|
|
|
*/ |
|
210
|
|
View Code Duplication |
public function getTotpSecret($userId) |
|
|
|
|
|
|
211
|
|
|
{ |
|
212
|
|
|
$this->addUser($userId); |
|
213
|
|
|
$stmt = $this->db->prepare( |
|
214
|
|
|
<<< 'SQL' |
|
215
|
|
|
SELECT |
|
216
|
|
|
totp_secret |
|
217
|
|
|
FROM |
|
218
|
|
|
users |
|
219
|
|
|
WHERE |
|
220
|
|
|
user_id = :user_id |
|
221
|
|
|
SQL |
|
222
|
|
|
); |
|
223
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
224
|
|
|
$stmt->execute(); |
|
225
|
|
|
|
|
226
|
|
|
return $stmt->fetchColumn(); |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
View Code Duplication |
public function setTotpSecret($userId, $totpSecret) |
|
|
|
|
|
|
230
|
|
|
{ |
|
231
|
|
|
$this->addUser($userId); |
|
232
|
|
|
$stmt = $this->db->prepare( |
|
233
|
|
|
<<< 'SQL' |
|
234
|
|
|
UPDATE |
|
235
|
|
|
users |
|
236
|
|
|
SET |
|
237
|
|
|
totp_secret = :totp_secret |
|
238
|
|
|
WHERE |
|
239
|
|
|
user_id = :user_id |
|
240
|
|
|
SQL |
|
241
|
|
|
); |
|
242
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
243
|
|
|
$stmt->bindValue(':totp_secret', $totpSecret, PDO::PARAM_STR); |
|
244
|
|
|
|
|
245
|
|
|
$stmt->execute(); |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
View Code Duplication |
public function deleteTotpSecret($userId) |
|
|
|
|
|
|
249
|
|
|
{ |
|
250
|
|
|
$this->addUser($userId); |
|
251
|
|
|
$stmt = $this->db->prepare( |
|
252
|
|
|
<<< 'SQL' |
|
253
|
|
|
UPDATE |
|
254
|
|
|
users |
|
255
|
|
|
SET |
|
256
|
|
|
totp_secret = NULL |
|
257
|
|
|
WHERE |
|
258
|
|
|
user_id = :user_id |
|
259
|
|
|
SQL |
|
260
|
|
|
); |
|
261
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
262
|
|
|
$stmt->execute(); |
|
263
|
|
|
} |
|
264
|
|
|
|
|
265
|
|
View Code Duplication |
public function setYubiKeyId($userId, $yubiKeyId) |
|
|
|
|
|
|
266
|
|
|
{ |
|
267
|
|
|
$this->addUser($userId); |
|
268
|
|
|
$stmt = $this->db->prepare( |
|
269
|
|
|
<<< 'SQL' |
|
270
|
|
|
UPDATE |
|
271
|
|
|
users |
|
272
|
|
|
SET |
|
273
|
|
|
yubi_key_id = :yubi_key_id |
|
274
|
|
|
WHERE |
|
275
|
|
|
user_id = :user_id |
|
276
|
|
|
SQL |
|
277
|
|
|
); |
|
278
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
279
|
|
|
$stmt->bindValue(':yubi_key_id', $yubiKeyId, PDO::PARAM_STR); |
|
280
|
|
|
|
|
281
|
|
|
$stmt->execute(); |
|
282
|
|
|
} |
|
283
|
|
|
|
|
284
|
|
|
/** |
|
285
|
|
|
* @return bool |
|
286
|
|
|
*/ |
|
287
|
|
View Code Duplication |
public function hasYubiKeyId($userId) |
|
|
|
|
|
|
288
|
|
|
{ |
|
289
|
|
|
$this->addUser($userId); |
|
290
|
|
|
$stmt = $this->db->prepare( |
|
291
|
|
|
<<< 'SQL' |
|
292
|
|
|
SELECT |
|
293
|
|
|
yubi_key_id |
|
294
|
|
|
FROM |
|
295
|
|
|
users |
|
296
|
|
|
WHERE |
|
297
|
|
|
user_id = :user_id |
|
298
|
|
|
SQL |
|
299
|
|
|
); |
|
300
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
301
|
|
|
$stmt->execute(); |
|
302
|
|
|
|
|
303
|
|
|
return !is_null($stmt->fetchColumn()); |
|
304
|
|
|
} |
|
305
|
|
|
|
|
306
|
|
|
/** |
|
307
|
|
|
* @return string|null |
|
308
|
|
|
*/ |
|
309
|
|
View Code Duplication |
public function getYubiKeyId($userId) |
|
|
|
|
|
|
310
|
|
|
{ |
|
311
|
|
|
$this->addUser($userId); |
|
312
|
|
|
$stmt = $this->db->prepare( |
|
313
|
|
|
<<< 'SQL' |
|
314
|
|
|
SELECT |
|
315
|
|
|
yubi_key_id |
|
316
|
|
|
FROM |
|
317
|
|
|
users |
|
318
|
|
|
WHERE |
|
319
|
|
|
user_id = :user_id |
|
320
|
|
|
SQL |
|
321
|
|
|
); |
|
322
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
323
|
|
|
$stmt->execute(); |
|
324
|
|
|
|
|
325
|
|
|
return $stmt->fetchColumn(); |
|
326
|
|
|
} |
|
327
|
|
|
|
|
328
|
|
View Code Duplication |
public function deleteYubiKeyId($userId) |
|
|
|
|
|
|
329
|
|
|
{ |
|
330
|
|
|
$this->addUser($userId); |
|
331
|
|
|
$stmt = $this->db->prepare( |
|
332
|
|
|
<<< 'SQL' |
|
333
|
|
|
UPDATE |
|
334
|
|
|
users |
|
335
|
|
|
SET |
|
336
|
|
|
yubi_key_id = NULL |
|
337
|
|
|
WHERE |
|
338
|
|
|
user_id = :user_id |
|
339
|
|
|
SQL |
|
340
|
|
|
); |
|
341
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
342
|
|
|
$stmt->execute(); |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
View Code Duplication |
public function deleteUser($userId) |
|
|
|
|
|
|
346
|
|
|
{ |
|
347
|
|
|
$this->addUser($userId); |
|
348
|
|
|
$stmt = $this->db->prepare( |
|
349
|
|
|
<<< 'SQL' |
|
350
|
|
|
DELETE FROM |
|
351
|
|
|
users |
|
352
|
|
|
WHERE |
|
353
|
|
|
user_id = :user_id |
|
354
|
|
|
SQL |
|
355
|
|
|
); |
|
356
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
357
|
|
|
$stmt->execute(); |
|
358
|
|
|
} |
|
359
|
|
|
|
|
360
|
|
View Code Duplication |
public function addCertificate($userId, $commonName, $displayName, DateTime $validFrom, DateTime $validTo) |
|
|
|
|
|
|
361
|
|
|
{ |
|
362
|
|
|
$this->addUser($userId); |
|
363
|
|
|
$stmt = $this->db->prepare( |
|
364
|
|
|
<<< 'SQL' |
|
365
|
|
|
INSERT INTO certificates |
|
366
|
|
|
(common_name, user_id, display_name, valid_from, valid_to) |
|
367
|
|
|
VALUES |
|
368
|
|
|
(:common_name, :user_id, :display_name, :valid_from, :valid_to) |
|
369
|
|
|
SQL |
|
370
|
|
|
); |
|
371
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
372
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
373
|
|
|
$stmt->bindValue(':display_name', $displayName, PDO::PARAM_STR); |
|
374
|
|
|
$stmt->bindValue(':valid_from', $validFrom->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
375
|
|
|
$stmt->bindValue(':valid_to', $validTo->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
376
|
|
|
$stmt->execute(); |
|
377
|
|
|
} |
|
378
|
|
|
|
|
379
|
|
|
/** |
|
380
|
|
|
* @return array |
|
381
|
|
|
*/ |
|
382
|
|
|
public function getCertificates($userId) |
|
383
|
|
|
{ |
|
384
|
|
|
$this->addUser($userId); |
|
385
|
|
|
$stmt = $this->db->prepare( |
|
386
|
|
|
<<< 'SQL' |
|
387
|
|
|
SELECT |
|
388
|
|
|
common_name, |
|
389
|
|
|
display_name, |
|
390
|
|
|
valid_from, |
|
391
|
|
|
valid_to, |
|
392
|
|
|
is_disabled |
|
393
|
|
|
FROM |
|
394
|
|
|
certificates |
|
395
|
|
|
WHERE |
|
396
|
|
|
user_id = :user_id |
|
397
|
|
|
SQL |
|
398
|
|
|
); |
|
399
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
400
|
|
|
$stmt->execute(); |
|
401
|
|
|
|
|
402
|
|
|
$certificateList = []; |
|
403
|
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { |
|
404
|
|
|
$row['is_disabled'] = (bool) $row['is_disabled']; |
|
405
|
|
|
$certificateList[] = $row; |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
return $certificateList; |
|
409
|
|
|
} |
|
410
|
|
|
|
|
411
|
|
|
public function disableCertificate($commonName) |
|
412
|
|
|
{ |
|
413
|
|
|
$stmt = $this->db->prepare( |
|
414
|
|
|
<<< 'SQL' |
|
415
|
|
|
UPDATE |
|
416
|
|
|
certificates |
|
417
|
|
|
SET |
|
418
|
|
|
is_disabled = 1 |
|
419
|
|
|
WHERE |
|
420
|
|
|
common_name = :common_name |
|
421
|
|
|
SQL |
|
422
|
|
|
); |
|
423
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
424
|
|
|
$stmt->execute(); |
|
425
|
|
|
} |
|
426
|
|
|
|
|
427
|
|
|
public function deleteCertificate($commonName) |
|
428
|
|
|
{ |
|
429
|
|
|
$stmt = $this->db->prepare( |
|
430
|
|
|
<<< 'SQL' |
|
431
|
|
|
DELETE FROM |
|
432
|
|
|
certificates |
|
433
|
|
|
WHERE |
|
434
|
|
|
common_name = :common_name |
|
435
|
|
|
SQL |
|
436
|
|
|
); |
|
437
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
438
|
|
|
$stmt->execute(); |
|
439
|
|
|
} |
|
440
|
|
|
|
|
441
|
|
|
public function enableCertificate($commonName) |
|
442
|
|
|
{ |
|
443
|
|
|
$stmt = $this->db->prepare( |
|
444
|
|
|
<<< 'SQL' |
|
445
|
|
|
UPDATE |
|
446
|
|
|
certificates |
|
447
|
|
|
SET |
|
448
|
|
|
is_disabled = 0 |
|
449
|
|
|
WHERE |
|
450
|
|
|
common_name = :common_name |
|
451
|
|
|
SQL |
|
452
|
|
|
); |
|
453
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
454
|
|
|
$stmt->execute(); |
|
455
|
|
|
} |
|
456
|
|
|
|
|
457
|
|
View Code Duplication |
public function disableUser($userId) |
|
|
|
|
|
|
458
|
|
|
{ |
|
459
|
|
|
$this->addUser($userId); |
|
460
|
|
|
$stmt = $this->db->prepare( |
|
461
|
|
|
<<< 'SQL' |
|
462
|
|
|
UPDATE |
|
463
|
|
|
users |
|
464
|
|
|
SET |
|
465
|
|
|
is_disabled = 1 |
|
466
|
|
|
WHERE |
|
467
|
|
|
user_id = :user_id |
|
468
|
|
|
SQL |
|
469
|
|
|
); |
|
470
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
471
|
|
|
$stmt->execute(); |
|
472
|
|
|
} |
|
473
|
|
|
|
|
474
|
|
|
public function enableUser($userId) |
|
475
|
|
|
{ |
|
476
|
|
|
$this->addUser($userId); |
|
477
|
|
|
$stmt = $this->db->prepare( |
|
478
|
|
|
<<< 'SQL' |
|
479
|
|
|
UPDATE |
|
480
|
|
|
users |
|
481
|
|
|
SET |
|
482
|
|
|
is_disabled = 0 |
|
483
|
|
|
WHERE |
|
484
|
|
|
user_id = :user_id |
|
485
|
|
|
SQL |
|
486
|
|
|
); |
|
487
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
488
|
|
|
$stmt->execute(); |
|
489
|
|
|
} |
|
490
|
|
|
|
|
491
|
|
|
/** |
|
492
|
|
|
* @return bool |
|
493
|
|
|
*/ |
|
494
|
|
View Code Duplication |
public function isDisabledUser($userId) |
|
|
|
|
|
|
495
|
|
|
{ |
|
496
|
|
|
$this->addUser($userId); |
|
497
|
|
|
$stmt = $this->db->prepare( |
|
498
|
|
|
<<< 'SQL' |
|
499
|
|
|
SELECT |
|
500
|
|
|
is_disabled |
|
501
|
|
|
FROM |
|
502
|
|
|
users |
|
503
|
|
|
WHERE |
|
504
|
|
|
user_id = :user_id |
|
505
|
|
|
SQL |
|
506
|
|
|
); |
|
507
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
508
|
|
|
$stmt->execute(); |
|
509
|
|
|
|
|
510
|
|
|
return (bool) $stmt->fetchColumn(); |
|
511
|
|
|
} |
|
512
|
|
|
|
|
513
|
|
|
/** |
|
514
|
|
|
* @return array |
|
515
|
|
|
*/ |
|
516
|
|
|
public function getAllLogEntries() |
|
517
|
|
|
{ |
|
518
|
|
|
$stmt = $this->db->prepare( |
|
519
|
|
|
<<< 'SQL' |
|
520
|
|
|
SELECT |
|
521
|
|
|
user_id, |
|
522
|
|
|
common_name, |
|
523
|
|
|
connected_at, |
|
524
|
|
|
disconnected_at, |
|
525
|
|
|
bytes_transferred |
|
526
|
|
|
FROM |
|
527
|
|
|
connection_log |
|
528
|
|
|
WHERE |
|
529
|
|
|
disconnected_at IS NOT NULL |
|
530
|
|
|
ORDER BY |
|
531
|
|
|
connected_at |
|
532
|
|
|
SQL |
|
533
|
|
|
); |
|
534
|
|
|
|
|
535
|
|
|
$stmt->execute(); |
|
536
|
|
|
|
|
537
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC); |
|
538
|
|
|
} |
|
539
|
|
|
|
|
540
|
|
View Code Duplication |
public function clientConnect($profileId, $commonName, $ip4, $ip6, DateTime $connectedAt) |
|
|
|
|
|
|
541
|
|
|
{ |
|
542
|
|
|
// this query is so complex, because we want to store the user_id in the |
|
543
|
|
|
// log as well, not just the common_name... the user may delete the |
|
544
|
|
|
// certificate, or the user account may be deleted... |
|
545
|
|
|
$stmt = $this->db->prepare( |
|
546
|
|
|
<<< 'SQL' |
|
547
|
|
|
INSERT INTO connection_log |
|
548
|
|
|
( |
|
549
|
|
|
user_id, |
|
550
|
|
|
profile_id, |
|
551
|
|
|
common_name, |
|
552
|
|
|
ip4, |
|
553
|
|
|
ip6, |
|
554
|
|
|
connected_at |
|
555
|
|
|
) |
|
556
|
|
|
VALUES |
|
557
|
|
|
( |
|
558
|
|
|
( |
|
559
|
|
|
SELECT |
|
560
|
|
|
u.user_id |
|
561
|
|
|
FROM |
|
562
|
|
|
users u, certificates c |
|
563
|
|
|
WHERE |
|
564
|
|
|
u.user_id = c.user_id |
|
565
|
|
|
AND |
|
566
|
|
|
c.common_name = :common_name |
|
567
|
|
|
), |
|
568
|
|
|
:profile_id, |
|
569
|
|
|
:common_name, |
|
570
|
|
|
:ip4, |
|
571
|
|
|
:ip6, |
|
572
|
|
|
:connected_at |
|
573
|
|
|
) |
|
574
|
|
|
SQL |
|
575
|
|
|
); |
|
576
|
|
|
|
|
577
|
|
|
$stmt->bindValue(':profile_id', $profileId, PDO::PARAM_STR); |
|
578
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
579
|
|
|
$stmt->bindValue(':ip4', $ip4, PDO::PARAM_STR); |
|
580
|
|
|
$stmt->bindValue(':ip6', $ip6, PDO::PARAM_STR); |
|
581
|
|
|
$stmt->bindValue(':connected_at', $connectedAt->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
582
|
|
|
$stmt->execute(); |
|
583
|
|
|
} |
|
584
|
|
|
|
|
585
|
|
|
public function clientDisconnect($profileId, $commonName, $ip4, $ip6, DateTime $connectedAt, DateTime $disconnectedAt, $bytesTransferred) |
|
586
|
|
|
{ |
|
587
|
|
|
$stmt = $this->db->prepare( |
|
588
|
|
|
<<< 'SQL' |
|
589
|
|
|
UPDATE |
|
590
|
|
|
connection_log |
|
591
|
|
|
SET |
|
592
|
|
|
disconnected_at = :disconnected_at, |
|
593
|
|
|
bytes_transferred = :bytes_transferred |
|
594
|
|
|
WHERE |
|
595
|
|
|
profile_id = :profile_id |
|
596
|
|
|
AND |
|
597
|
|
|
common_name = :common_name |
|
598
|
|
|
AND |
|
599
|
|
|
ip4 = :ip4 |
|
600
|
|
|
AND |
|
601
|
|
|
ip6 = :ip6 |
|
602
|
|
|
AND |
|
603
|
|
|
connected_at = :connected_at |
|
604
|
|
|
SQL |
|
605
|
|
|
); |
|
606
|
|
|
|
|
607
|
|
|
$stmt->bindValue(':profile_id', $profileId, PDO::PARAM_STR); |
|
608
|
|
|
$stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR); |
|
609
|
|
|
$stmt->bindValue(':ip4', $ip4, PDO::PARAM_STR); |
|
610
|
|
|
$stmt->bindValue(':ip6', $ip6, PDO::PARAM_STR); |
|
611
|
|
|
$stmt->bindValue(':connected_at', $connectedAt->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
612
|
|
|
$stmt->bindValue(':disconnected_at', $disconnectedAt->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
613
|
|
|
$stmt->bindValue(':bytes_transferred', $bytesTransferred, PDO::PARAM_INT); |
|
614
|
|
|
$stmt->execute(); |
|
615
|
|
|
} |
|
616
|
|
|
|
|
617
|
|
|
/** |
|
618
|
|
|
* @return array|false |
|
619
|
|
|
*/ |
|
620
|
|
View Code Duplication |
public function getLogEntry(DateTime $dateTime, $ipAddress) |
|
|
|
|
|
|
621
|
|
|
{ |
|
622
|
|
|
$stmt = $this->db->prepare( |
|
623
|
|
|
<<< 'SQL' |
|
624
|
|
|
SELECT |
|
625
|
|
|
user_id, |
|
626
|
|
|
profile_id, |
|
627
|
|
|
common_name, |
|
628
|
|
|
ip4, |
|
629
|
|
|
ip6, |
|
630
|
|
|
connected_at, |
|
631
|
|
|
disconnected_at |
|
632
|
|
|
FROM |
|
633
|
|
|
connection_log |
|
634
|
|
|
WHERE |
|
635
|
|
|
(ip4 = :ip_address OR ip6 = :ip_address) |
|
636
|
|
|
AND |
|
637
|
|
|
connected_at < :date_time |
|
638
|
|
|
AND |
|
639
|
|
|
(disconnected_at > :date_time OR disconnected_at IS NULL) |
|
640
|
|
|
SQL |
|
641
|
|
|
); |
|
642
|
|
|
$stmt->bindValue(':ip_address', $ipAddress, PDO::PARAM_STR); |
|
643
|
|
|
$stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
644
|
|
|
$stmt->execute(); |
|
645
|
|
|
|
|
646
|
|
|
// XXX can this also contain multiple results? I don't think so, but |
|
647
|
|
|
// make sure! |
|
648
|
|
|
return $stmt->fetch(PDO::FETCH_ASSOC); |
|
649
|
|
|
} |
|
650
|
|
|
|
|
651
|
|
|
/** |
|
652
|
|
|
* @return int |
|
653
|
|
|
*/ |
|
654
|
|
View Code Duplication |
public function getTotpAttemptCount($userId) |
|
|
|
|
|
|
655
|
|
|
{ |
|
656
|
|
|
$this->addUser($userId); |
|
657
|
|
|
$stmt = $this->db->prepare( |
|
658
|
|
|
<<< 'SQL' |
|
659
|
|
|
SELECT |
|
660
|
|
|
COUNT(*) |
|
661
|
|
|
FROM |
|
662
|
|
|
totp_log |
|
663
|
|
|
WHERE user_id = :user_id |
|
664
|
|
|
SQL |
|
665
|
|
|
); |
|
666
|
|
|
|
|
667
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
668
|
|
|
$stmt->execute(); |
|
669
|
|
|
|
|
670
|
|
|
return (int) $stmt->fetchColumn(); |
|
671
|
|
|
} |
|
672
|
|
|
|
|
673
|
|
|
/** |
|
674
|
|
|
* @return bool true if recording succeeds, false if it cannot due to replay |
|
675
|
|
|
*/ |
|
676
|
|
|
public function recordTotpKey($userId, $totpKey) |
|
677
|
|
|
{ |
|
678
|
|
|
$this->addUser($userId); |
|
679
|
|
|
$stmt = $this->db->prepare( |
|
680
|
|
|
<<< 'SQL' |
|
681
|
|
|
INSERT INTO totp_log |
|
682
|
|
|
(user_id, totp_key, date_time) |
|
683
|
|
|
VALUES |
|
684
|
|
|
(:user_id, :totp_key, :date_time) |
|
685
|
|
|
SQL |
|
686
|
|
|
); |
|
687
|
|
|
|
|
688
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
689
|
|
|
$stmt->bindValue(':totp_key', $totpKey, PDO::PARAM_STR); |
|
690
|
|
|
$stmt->bindValue(':date_time', $this->dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
691
|
|
|
|
|
692
|
|
|
try { |
|
693
|
|
|
$stmt->execute(); |
|
694
|
|
|
} catch (PDOException $e) { |
|
695
|
|
|
// unable to record the TOTP, most likely replay |
|
696
|
|
|
return false; |
|
697
|
|
|
} |
|
698
|
|
|
|
|
699
|
|
|
return true; |
|
700
|
|
|
} |
|
701
|
|
|
|
|
702
|
|
View Code Duplication |
public function cleanConnectionLog(DateTime $dateTime) |
|
|
|
|
|
|
703
|
|
|
{ |
|
704
|
|
|
$stmt = $this->db->prepare( |
|
705
|
|
|
<<< 'SQL' |
|
706
|
|
|
DELETE FROM |
|
707
|
|
|
connection_log |
|
708
|
|
|
WHERE |
|
709
|
|
|
connected_at < :date_time |
|
710
|
|
|
AND |
|
711
|
|
|
disconnected_at IS NOT NULL |
|
712
|
|
|
SQL |
|
713
|
|
|
); |
|
714
|
|
|
|
|
715
|
|
|
$stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
716
|
|
|
|
|
717
|
|
|
return $stmt->execute(); |
|
718
|
|
|
} |
|
719
|
|
|
|
|
720
|
|
View Code Duplication |
public function cleanUserMessages(DateTime $dateTime) |
|
|
|
|
|
|
721
|
|
|
{ |
|
722
|
|
|
$stmt = $this->db->prepare( |
|
723
|
|
|
<<< 'SQL' |
|
724
|
|
|
DELETE FROM |
|
725
|
|
|
user_messages |
|
726
|
|
|
WHERE |
|
727
|
|
|
date_time < :date_time |
|
728
|
|
|
SQL |
|
729
|
|
|
); |
|
730
|
|
|
|
|
731
|
|
|
$stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
732
|
|
|
|
|
733
|
|
|
return $stmt->execute(); |
|
734
|
|
|
} |
|
735
|
|
|
|
|
736
|
|
View Code Duplication |
public function cleanTotpLog(DateTime $dateTime) |
|
|
|
|
|
|
737
|
|
|
{ |
|
738
|
|
|
$stmt = $this->db->prepare( |
|
739
|
|
|
<<< 'SQL' |
|
740
|
|
|
DELETE FROM |
|
741
|
|
|
totp_log |
|
742
|
|
|
WHERE |
|
743
|
|
|
date_time < :date_time |
|
744
|
|
|
SQL |
|
745
|
|
|
); |
|
746
|
|
|
|
|
747
|
|
|
$stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
748
|
|
|
|
|
749
|
|
|
return $stmt->execute(); |
|
750
|
|
|
} |
|
751
|
|
|
|
|
752
|
|
|
/** |
|
753
|
|
|
* @return array |
|
754
|
|
|
*/ |
|
755
|
|
View Code Duplication |
public function systemMessages($type) |
|
|
|
|
|
|
756
|
|
|
{ |
|
757
|
|
|
$stmt = $this->db->prepare( |
|
758
|
|
|
<<< 'SQL' |
|
759
|
|
|
SELECT |
|
760
|
|
|
id, message, date_time |
|
761
|
|
|
FROM |
|
762
|
|
|
system_messages |
|
763
|
|
|
WHERE |
|
764
|
|
|
type = :type |
|
765
|
|
|
SQL |
|
766
|
|
|
); |
|
767
|
|
|
|
|
768
|
|
|
$stmt->bindValue(':type', $type, PDO::PARAM_STR); |
|
769
|
|
|
$stmt->execute(); |
|
770
|
|
|
|
|
771
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC); |
|
772
|
|
|
} |
|
773
|
|
|
|
|
774
|
|
|
public function addSystemMessage($type, $message) |
|
775
|
|
|
{ |
|
776
|
|
|
$stmt = $this->db->prepare( |
|
777
|
|
|
<<< 'SQL' |
|
778
|
|
|
INSERT INTO system_messages |
|
779
|
|
|
(type, message, date_time) |
|
780
|
|
|
VALUES |
|
781
|
|
|
(:type, :message, :date_time) |
|
782
|
|
|
SQL |
|
783
|
|
|
); |
|
784
|
|
|
|
|
785
|
|
|
$stmt->bindValue(':type', $type, PDO::PARAM_STR); |
|
786
|
|
|
$stmt->bindValue(':message', $message, PDO::PARAM_STR); |
|
787
|
|
|
$stmt->bindValue(':date_time', $this->dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
788
|
|
|
$stmt->execute(); |
|
789
|
|
|
} |
|
790
|
|
|
|
|
791
|
|
|
public function deleteSystemMessage($messageId) |
|
792
|
|
|
{ |
|
793
|
|
|
$stmt = $this->db->prepare( |
|
794
|
|
|
<<< 'SQL' |
|
795
|
|
|
DELETE FROM |
|
796
|
|
|
system_messages |
|
797
|
|
|
WHERE id = :message_id |
|
798
|
|
|
SQL |
|
799
|
|
|
); |
|
800
|
|
|
|
|
801
|
|
|
$stmt->bindValue(':message_id', $messageId, PDO::PARAM_INT); |
|
802
|
|
|
$stmt->execute(); |
|
803
|
|
|
} |
|
804
|
|
|
|
|
805
|
|
|
/** |
|
806
|
|
|
* @return array |
|
807
|
|
|
*/ |
|
808
|
|
View Code Duplication |
public function userMessages($userId) |
|
|
|
|
|
|
809
|
|
|
{ |
|
810
|
|
|
$this->addUser($userId); |
|
811
|
|
|
$stmt = $this->db->prepare( |
|
812
|
|
|
<<< 'SQL' |
|
813
|
|
|
SELECT |
|
814
|
|
|
id, type, message, date_time |
|
815
|
|
|
FROM |
|
816
|
|
|
user_messages |
|
817
|
|
|
WHERE |
|
818
|
|
|
user_id = :user_id |
|
819
|
|
|
ORDER BY |
|
820
|
|
|
date_time DESC |
|
821
|
|
|
SQL |
|
822
|
|
|
); |
|
823
|
|
|
|
|
824
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
825
|
|
|
$stmt->execute(); |
|
826
|
|
|
|
|
827
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC); |
|
828
|
|
|
} |
|
829
|
|
|
|
|
830
|
|
View Code Duplication |
public function addUserMessage($userId, $type, $message) |
|
|
|
|
|
|
831
|
|
|
{ |
|
832
|
|
|
$this->addUser($userId); |
|
833
|
|
|
$stmt = $this->db->prepare( |
|
834
|
|
|
<<< 'SQL' |
|
835
|
|
|
INSERT INTO user_messages |
|
836
|
|
|
(user_id, type, message, date_time) |
|
837
|
|
|
VALUES |
|
838
|
|
|
(:user_id, :type, :message, :date_time) |
|
839
|
|
|
SQL |
|
840
|
|
|
); |
|
841
|
|
|
|
|
842
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
843
|
|
|
$stmt->bindValue(':type', $type, PDO::PARAM_STR); |
|
844
|
|
|
$stmt->bindValue(':message', $message, PDO::PARAM_STR); |
|
845
|
|
|
$stmt->bindValue(':date_time', $this->dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
846
|
|
|
$stmt->execute(); |
|
847
|
|
|
} |
|
848
|
|
|
|
|
849
|
|
|
// TokenStorageInterface |
|
850
|
|
|
|
|
851
|
|
|
/** |
|
852
|
|
|
* @param string $userId |
|
853
|
|
|
* |
|
854
|
|
|
* @return array |
|
855
|
|
|
*/ |
|
856
|
|
|
public function getAccessToken($userId) |
|
857
|
|
|
{ |
|
858
|
|
|
$vootToken = $this->getVootToken($userId); |
|
859
|
|
|
if (is_null($vootToken)) { |
|
860
|
|
|
return []; |
|
861
|
|
|
} |
|
862
|
|
|
|
|
863
|
|
|
return [ |
|
864
|
|
|
AccessToken::fromStorage($vootToken), |
|
865
|
|
|
]; |
|
866
|
|
|
} |
|
867
|
|
|
|
|
868
|
|
|
/** |
|
869
|
|
|
* @param string $userId |
|
870
|
|
|
* @param AccessToken $accessToken |
|
871
|
|
|
*/ |
|
872
|
|
|
public function addAccessToken($userId, AccessToken $accessToken) |
|
873
|
|
|
{ |
|
874
|
|
|
$this->setVootToken($userId, $accessToken); |
|
875
|
|
|
} |
|
876
|
|
|
|
|
877
|
|
|
/** |
|
878
|
|
|
* @param string $userId |
|
879
|
|
|
* @param AccessToken $accessToken |
|
880
|
|
|
*/ |
|
881
|
|
|
public function deleteAccessToken($userId, AccessToken $accessToken) |
|
882
|
|
|
{ |
|
883
|
|
|
$this->deleteVootToken($userId); |
|
884
|
|
|
} |
|
885
|
|
|
|
|
886
|
|
|
public function init() |
|
887
|
|
|
{ |
|
888
|
|
|
$queryList = []; |
|
889
|
|
|
$queryList[] = |
|
890
|
|
|
<<< 'SQL' |
|
891
|
|
|
CREATE TABLE IF NOT EXISTS users ( |
|
892
|
|
|
user_id VARCHAR(255) NOT NULL PRIMARY KEY UNIQUE, |
|
893
|
|
|
voot_token TEXT DEFAULT NULL, |
|
894
|
|
|
totp_secret VARCHAR(255) DEFAULT NULL, |
|
895
|
|
|
yubi_key_id VARCHAR(255) DEFAULT NULL, |
|
896
|
|
|
date_time DATETIME NOT NULL, |
|
897
|
|
|
is_disabled BOOLEAN DEFAULT 0 NOT NULL |
|
898
|
|
|
) |
|
899
|
|
|
SQL; |
|
900
|
|
|
|
|
901
|
|
|
$queryList[] = |
|
902
|
|
|
<<< 'SQL' |
|
903
|
|
|
CREATE TABLE IF NOT EXISTS certificates ( |
|
904
|
|
|
common_name VARCHAR(255) UNIQUE NOT NULL, |
|
905
|
|
|
display_name VARCHAR(255) NOT NULL, |
|
906
|
|
|
valid_from DATETIME NOT NULL, |
|
907
|
|
|
valid_to DATETIME NOT NULL, |
|
908
|
|
|
is_disabled BOOLEAN DEFAULT 0, |
|
909
|
|
|
user_id VARCHAR(255) NOT NULL REFERENCES users(user_id) ON DELETE CASCADE |
|
910
|
|
|
) |
|
911
|
|
|
SQL; |
|
912
|
|
|
|
|
913
|
|
|
$queryList[] = |
|
914
|
|
|
<<< 'SQL' |
|
915
|
|
|
CREATE TABLE IF NOT EXISTS totp_log ( |
|
916
|
|
|
totp_key VARCHAR(255) NOT NULL, |
|
917
|
|
|
date_time DATETIME NOT NULL, |
|
918
|
|
|
user_id VARCHAR(255) NOT NULL REFERENCES users(user_id) ON DELETE CASCADE, |
|
919
|
|
|
UNIQUE (user_id, totp_key) |
|
920
|
|
|
) |
|
921
|
|
|
SQL; |
|
922
|
|
|
|
|
923
|
|
|
$queryList[] = |
|
924
|
|
|
<<< 'SQL' |
|
925
|
|
|
CREATE TABLE IF NOT EXISTS connection_log ( |
|
926
|
|
|
user_id VARCHAR(255) NOT NULL, |
|
927
|
|
|
common_name VARCHAR(255) NOT NULL, |
|
928
|
|
|
profile_id VARCHAR(255) NOT NULL, |
|
929
|
|
|
ip4 VARCHAR(255) NOT NULL, |
|
930
|
|
|
ip6 VARCHAR(255) NOT NULL, |
|
931
|
|
|
connected_at DATETIME NOT NULL, |
|
932
|
|
|
disconnected_at DATETIME DEFAULT NULL, |
|
933
|
|
|
bytes_transferred INTEGER DEFAULT NULL |
|
934
|
|
|
) |
|
935
|
|
|
SQL; |
|
936
|
|
|
|
|
937
|
|
|
$queryList[] = |
|
938
|
|
|
<<< 'SQL' |
|
939
|
|
|
CREATE TABLE IF NOT EXISTS system_messages ( |
|
940
|
|
|
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, |
|
941
|
|
|
type VARCHAR(255) NOT NULL DEFAULT "notification", |
|
942
|
|
|
message TINYTEXT NOT NULL, |
|
943
|
|
|
date_time DATETIME NOT NULL |
|
944
|
|
|
) |
|
945
|
|
|
SQL; |
|
946
|
|
|
|
|
947
|
|
|
$queryList[] = |
|
948
|
|
|
<<< 'SQL' |
|
949
|
|
|
CREATE TABLE IF NOT EXISTS user_messages ( |
|
950
|
|
|
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, |
|
951
|
|
|
type VARCHAR(255) NOT NULL DEFAULT "notification", |
|
952
|
|
|
message TINYTEXT NOT NULL, |
|
953
|
|
|
date_time DATETIME NOT NULL, |
|
954
|
|
|
user_id VARCHAR(255) NOT NULL REFERENCES users(user_id) ON DELETE CASCADE |
|
955
|
|
|
) |
|
956
|
|
|
SQL; |
|
957
|
|
|
|
|
958
|
|
|
foreach ($queryList as $query) { |
|
959
|
|
|
if ('sqlite' === $this->db->getAttribute(PDO::ATTR_DRIVER_NAME)) { |
|
960
|
|
|
$query = str_replace('AUTO_INCREMENT', 'AUTOINCREMENT', $query); |
|
961
|
|
|
} |
|
962
|
|
|
$this->db->query($query); |
|
963
|
|
|
} |
|
964
|
|
|
} |
|
965
|
|
|
|
|
966
|
|
View Code Duplication |
private function addUser($userId) |
|
|
|
|
|
|
967
|
|
|
{ |
|
968
|
|
|
$stmt = $this->db->prepare( |
|
969
|
|
|
<<< 'SQL' |
|
970
|
|
|
SELECT |
|
971
|
|
|
COUNT(*) |
|
972
|
|
|
FROM |
|
973
|
|
|
users |
|
974
|
|
|
WHERE user_id = :user_id |
|
975
|
|
|
SQL |
|
976
|
|
|
); |
|
977
|
|
|
|
|
978
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
979
|
|
|
$stmt->execute(); |
|
980
|
|
|
|
|
981
|
|
|
if (1 !== (int) $stmt->fetchColumn()) { |
|
982
|
|
|
// user does not exist yet |
|
983
|
|
|
$stmt = $this->db->prepare( |
|
984
|
|
|
<<< 'SQL' |
|
985
|
|
|
INSERT INTO |
|
986
|
|
|
users ( |
|
987
|
|
|
user_id, |
|
988
|
|
|
date_time |
|
989
|
|
|
) |
|
990
|
|
|
VALUES ( |
|
991
|
|
|
:user_id, |
|
992
|
|
|
:date_time |
|
993
|
|
|
) |
|
994
|
|
|
SQL |
|
995
|
|
|
); |
|
996
|
|
|
$stmt->bindValue(':user_id', $userId, PDO::PARAM_STR); |
|
997
|
|
|
$stmt->bindValue(':date_time', $this->dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR); |
|
998
|
|
|
$stmt->execute(); |
|
999
|
|
|
} |
|
1000
|
|
|
} |
|
1001
|
|
|
} |
|
1002
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.