GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 392d49...015953 )
by François
02:01
created

Storage::hasTotpSecret()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 9

Duplication

Lines 18
Ratio 100 %

Importance

Changes 0
Metric Value
dl 18
loc 18
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 1
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 PDO;
23
use PDOException;
24
25
class Storage
26
{
27
    /** @var \PDO */
28
    private $db;
29
30
    public function __construct(PDO $db)
31
    {
32
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
33
        $this->db = $db;
34
35
        if ('sqlite' === $this->db->getAttribute(PDO::ATTR_DRIVER_NAME)) {
36
            $this->db->query('PRAGMA foreign_keys = ON');
37
        }
38
    }
39
40
    public function getId($userId)
41
    {
42
        $stmt = $this->db->prepare(
43
<<< 'SQL'
44
    SELECT 
45
        id
46
    FROM 
47
        users
48
    WHERE user_id = :user_id
49
SQL
50
        );
51
52
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_STR);
53
        $stmt->execute();
54
        if (false !== $result = $stmt->fetch(PDO::FETCH_ASSOC)) {
55
            return $result['id'];
56
        }
57
58
        // user does not exist yet, add it
59
        $stmt = $this->db->prepare(
60
<<< 'SQL'
61
    INSERT INTO 
62
        users (
63
            user_id
64
        )
65
    VALUES (
66
        :user_id
67
    )
68
SQL
69
        );
70
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_STR);
71
        $stmt->execute();
72
73
        return $this->db->lastInsertId('id');
74
    }
75
76
    public function getUsers()
77
    {
78
        $stmt = $this->db->prepare(
79
<<< 'SQL'
80
    SELECT
81
        user_id, 
82
        is_disabled
83
    FROM 
84
        users
85
SQL
86
        );
87
        $stmt->execute();
88
89
        $userList = [];
90
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $result) {
91
            $userList[] = [
92
                'user_id' => $result['user_id'],
93
                'is_disabled' => (bool) $result['is_disabled'],
94
            ];
95
        }
96
97
        return $userList;
98
    }
99
100 View Code Duplication
    public function getUserCertificateInfo($commonName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
101
    {
102
        $stmt = $this->db->prepare(
103
<<< 'SQL'
104
    SELECT 
105
        u.user_id AS user_id, 
106
        u.is_disabled AS user_is_disabled,
107
        c.display_name AS display_name,
108
        c.is_disabled AS certificate_is_disabled 
109
    FROM 
110
        users u, certificates c 
111
    WHERE 
112
        u.id = c.user_id AND 
113
        c.common_name = :common_name
114
SQL
115
        );
116
117
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
118
        $stmt->execute();
119
120
        return $stmt->fetch(PDO::FETCH_ASSOC);
121
    }
122
123 View Code Duplication
    public function getVootToken($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
124
    {
125
        $userId = $this->getId($userId);
126
        $stmt = $this->db->prepare(
127
<<< 'SQL'
128
    SELECT
129
        voot_token
130
    FROM 
131
        voot_tokens
132
    WHERE 
133
        user_id = :user_id
134
SQL
135
        );
136
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
137
        $stmt->execute();
138
139
        return $stmt->fetchColumn();
140
    }
141
142 View Code Duplication
    public function setVootToken($userId, $vootToken)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
143
    {
144
        $userId = $this->getId($userId);
145
        $stmt = $this->db->prepare(
146
<<< 'SQL'
147
    INSERT INTO voot_tokens 
148
        (user_id, voot_token) 
149
    VALUES
150
        (:user_id, :voot_token)
151
SQL
152
        );
153
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
154
        $stmt->bindValue(':voot_token', $vootToken, PDO::PARAM_STR);
155
156
        $stmt->execute();
157
158
        // XXX deal with errors!
159
        return 1 === $stmt->rowCount();
160
    }
161
162 View Code Duplication
    public function hasVootToken($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
163
    {
164
        $userId = $this->getId($userId);
165
        $stmt = $this->db->prepare(
166
<<< 'SQL'
167
    SELECT
168
        COUNT(*)
169
    FROM 
170
        voot_tokens
171
    WHERE 
172
        user_id = :user_id
173
SQL
174
        );
175
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
176
        $stmt->execute();
177
178
        return 1 === (int) $stmt->fetchColumn();
179
    }
180
181 View Code Duplication
    public function deleteVootToken($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
182
    {
183
        $userId = $this->getId($userId);
184
        $stmt = $this->db->prepare(
185
<<< 'SQL'
186
    DELETE FROM 
187
        voot_tokens 
188
    WHERE 
189
        user_id = :user_id
190
SQL
191
        );
192
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
193
194
        $stmt->execute();
195
        // XXX error handling!
196
        return 1 === $stmt->rowCount();
197
    }
198
199 View Code Duplication
    public function hasTotpSecret($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
200
    {
201
        $userId = $this->getId($userId);
202
        $stmt = $this->db->prepare(
203
<<< 'SQL'
204
    SELECT
205
        COUNT(*)
206
    FROM 
207
        totp_secrets
208
    WHERE 
209
        user_id = :user_id
210
SQL
211
        );
212
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
213
        $stmt->execute();
214
215
        return 1 === (int) $stmt->fetchColumn();
216
    }
217
218 View Code Duplication
    public function getTotpSecret($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
219
    {
220
        $userId = $this->getId($userId);
221
        $stmt = $this->db->prepare(
222
<<< 'SQL'
223
    SELECT
224
        totp_secret
225
    FROM 
226
        totp_secrets
227
    WHERE 
228
        user_id = :user_id
229
SQL
230
        );
231
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
232
        $stmt->execute();
233
234
        return $stmt->fetchColumn();
235
    }
236
237
    public function setTotpSecret($userId, $totpSecret)
238
    {
239
        $userId = $this->getId($userId);
240
        $stmt = $this->db->prepare(
241
<<< 'SQL'
242
    INSERT INTO totp_secrets 
243
        (user_id, totp_secret) 
244
    VALUES
245
        (:user_id, :totp_secret)
246
SQL
247
        );
248
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
249
        $stmt->bindValue(':totp_secret', $totpSecret, PDO::PARAM_STR);
250
251
        try {
252
            $stmt->execute();
253
254
            return true;
255
        } catch (PDOException $e) {
256
            // unable to add the TOTP secret, probably uniqueness contrains
257
            return false;
258
        }
259
    }
260
261 View Code Duplication
    public function deleteTotpSecret($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
262
    {
263
        $userId = $this->getId($userId);
264
        $stmt = $this->db->prepare(
265
<<< 'SQL'
266
    DELETE FROM 
267
        totp_secrets 
268
    WHERE 
269
        user_id = :user_id
270
SQL
271
        );
272
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
273
274
        $stmt->execute();
275
276
        // XXX error handling?
277
        return 1 === $stmt->rowCount();
278
    }
279
280 View Code Duplication
    public function deleteUser($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
281
    {
282
        $userId = $this->getId($userId);
283
        $stmt = $this->db->prepare(
284
<<< 'SQL'
285
    DELETE FROM 
286
        users 
287
    WHERE 
288
        id = :user_id
289
SQL
290
        );
291
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
292
293
        $stmt->execute();
294
        // XXX error handling?
295
        return 1 === $stmt->rowCount();
296
    }
297
298
    public function addCertificate($userId, $commonName, $displayName, DateTime $validFrom, DateTime $validTo)
299
    {
300
        $userId = $this->getId($userId);
301
        $stmt = $this->db->prepare(
302
<<< 'SQL'
303
    INSERT INTO certificates 
304
        (common_name, user_id, display_name, valid_from, valid_to)
305
    VALUES
306
        (:common_name, :user_id, :display_name, :valid_from, :valid_to)
307
SQL
308
        );
309
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
310
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
311
        $stmt->bindValue(':display_name', $displayName, PDO::PARAM_STR);
312
        $stmt->bindValue(':valid_from', $validFrom->format('Y-m-d H:i:s'), PDO::PARAM_STR);
313
        $stmt->bindValue(':valid_to', $validTo->format('Y-m-d H:i:s'), PDO::PARAM_STR);
314
315
        $stmt->execute();
316
        // XXX
317
        return 1 === $stmt->rowCount();
318
    }
319
320
    public function getCertificates($userId)
321
    {
322
        $userId = $this->getId($userId);
323
        $stmt = $this->db->prepare(
324
<<< 'SQL'
325
    SELECT
326
        common_name, 
327
        display_name, 
328
        valid_from, 
329
        valid_to, 
330
        is_disabled
331
    FROM 
332
        certificates
333
    WHERE 
334
        user_id = :user_id
335
SQL
336
        );
337
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
338
        $stmt->execute();
339
340
        $certificateList = [];
341
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $result) {
342
            $result['is_disabled'] = (bool) $result['is_disabled'];
343
            $certificateList[] = $result;
344
        }
345
346
        return $certificateList;
347
    }
348
349 View Code Duplication
    public function disableCertificate($commonName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
350
    {
351
        $stmt = $this->db->prepare(
352
<<< 'SQL'
353
    UPDATE 
354
        certificates 
355
    SET 
356
        is_disabled = 1 
357
    WHERE
358
        common_name = :common_name
359
SQL
360
        );
361
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
362
363
        $stmt->execute();
364
        // XXX
365
        return 1 === $stmt->rowCount();
366
    }
367
368 View Code Duplication
    public function deleteCertificate($commonName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
369
    {
370
        $stmt = $this->db->prepare(
371
<<< 'SQL'
372
    DELETE FROM 
373
        certificates 
374
    WHERE 
375
        common_name = :common_name
376
SQL
377
        );
378
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
379
380
        $stmt->execute();
381
        // XXX
382
        return 1 === $stmt->rowCount();
383
    }
384
385 View Code Duplication
    public function enableCertificate($commonName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
386
    {
387
        $stmt = $this->db->prepare(
388
<<< 'SQL'
389
    UPDATE 
390
        certificates 
391
    SET 
392
        is_disabled = 0 
393
    WHERE 
394
        common_name = :common_name
395
SQL
396
        );
397
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
398
399
        $stmt->execute();
400
        // XXX
401
        return 1 === $stmt->rowCount();
402
    }
403
404 View Code Duplication
    public function disableUser($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
405
    {
406
        $userId = $this->getId($userId);
407
        $stmt = $this->db->prepare(
408
<<< 'SQL'
409
    UPDATE
410
        users 
411
    SET 
412
        is_disabled = 1 
413
    WHERE 
414
        id = :user_id
415
SQL
416
        );
417
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
418
419
        $stmt->execute();
420
421
        // XXX it seems on update the rowCount is always 1, even if nothing was
422
        // modified?
423
        return 1 === $stmt->rowCount();
424
    }
425
426 View Code Duplication
    public function enableUser($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
427
    {
428
        $userId = $this->getId($userId);
429
        $stmt = $this->db->prepare(
430
<<< 'SQL'
431
    UPDATE
432
        users 
433
    SET 
434
        is_disabled = 0 
435
    WHERE 
436
        id = :user_id
437
SQL
438
        );
439
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
440
441
        $stmt->execute();
442
443
        // XXX it seems on update the rowCount is always 1, even if nothing was
444
        // modified?
445
        return 1 === $stmt->rowCount();
446
    }
447
448 View Code Duplication
    public function isDisabledUser($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
449
    {
450
        $userId = $this->getId($userId);
451
        $stmt = $this->db->prepare(
452
<<< 'SQL'
453
    SELECT
454
        COUNT(*)
455
    FROM 
456
        users
457
    WHERE 
458
        id = :user_id 
459
    AND 
460
        is_disabled = 1
461
SQL
462
        );
463
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
464
        $stmt->execute();
465
466
        return 1 === (int) $stmt->fetchColumn();
467
    }
468
469
    public function getAllLogEntries()
470
    {
471
        $stmt = $this->db->prepare(
472
<<< 'SQL'
473
    SELECT 
474
        user_id,
475
        common_name, 
476
        connected_at, 
477
        disconnected_at, 
478
        bytes_transferred
479
    FROM 
480
        connection_log
481
    WHERE
482
        disconnected_at IS NOT NULL
483
    ORDER BY
484
        connected_at
485
SQL
486
        );
487
488
        $stmt->execute();
489
490
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
491
    }
492
493 View Code Duplication
    public function clientConnect($profileId, $commonName, $ip4, $ip6, DateTime $connectedAt)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
494
    {
495
        // this query is so complex, because we want to store the user_id in the
496
        // log as well, not just the common_name... the user may delete the
497
        // certificate, or the user account may be deleted...
498
        $stmt = $this->db->prepare(
499
<<< 'SQL'
500
    INSERT INTO connection_log 
501
        (
502
            user_id,
503
            profile_id,
504
            common_name,
505
            ip4,
506
            ip6,
507
            connected_at
508
        ) 
509
    VALUES
510
        (
511
            (
512
                SELECT
513
                    u.user_id
514
                FROM 
515
                    users u, certificates c
516
                WHERE
517
                    u.id = c.user_id
518
                AND
519
                    c.common_name = :common_name
520
            ),                
521
            :profile_id, 
522
            :common_name,
523
            :ip4,
524
            :ip6,
525
            :connected_at
526
        )
527
SQL
528
        );
529
530
        $stmt->bindValue(':profile_id', $profileId, PDO::PARAM_STR);
531
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
532
        $stmt->bindValue(':ip4', $ip4, PDO::PARAM_STR);
533
        $stmt->bindValue(':ip6', $ip6, PDO::PARAM_STR);
534
        $stmt->bindValue(':connected_at', $connectedAt->format('Y-m-d H:i:s'), PDO::PARAM_STR);
535
536
        $stmt->execute();
537
        // XXX
538
        return 1 === $stmt->rowCount();
539
    }
540
541
    public function clientDisconnect($profileId, $commonName, $ip4, $ip6, DateTime $connectedAt, DateTime $disconnectedAt, $bytesTransferred)
542
    {
543
        $stmt = $this->db->prepare(
544
<<< 'SQL'
545
    UPDATE 
546
        connection_log
547
    SET 
548
        disconnected_at = :disconnected_at, 
549
        bytes_transferred = :bytes_transferred
550
    WHERE 
551
        profile_id = :profile_id 
552
    AND
553
        common_name = :common_name 
554
    AND
555
        ip4 = :ip4 
556
    AND
557
        ip6 = :ip6 
558
    AND
559
        connected_at = :connected_at
560
SQL
561
        );
562
563
        $stmt->bindValue(':profile_id', $profileId, PDO::PARAM_STR);
564
        $stmt->bindValue(':common_name', $commonName, PDO::PARAM_STR);
565
        $stmt->bindValue(':ip4', $ip4, PDO::PARAM_STR);
566
        $stmt->bindValue(':ip6', $ip6, PDO::PARAM_STR);
567
        $stmt->bindValue(':connected_at', $connectedAt->format('Y-m-d H:i:s'), PDO::PARAM_STR);
568
        $stmt->bindValue(':disconnected_at', $disconnectedAt->format('Y-m-d H:i:s'), PDO::PARAM_STR);
569
        $stmt->bindValue(':bytes_transferred', $bytesTransferred, PDO::PARAM_INT);
570
571
        $stmt->execute();
572
573
        // XXX
574
        return 1 === $stmt->rowCount();
575
    }
576
577 View Code Duplication
    public function getLogEntry($dateTimeUnix, $ipAddress)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
578
    {
579
        $stmt = $this->db->prepare(
580
<<< 'SQL'
581
    SELECT 
582
        user_id,
583
        profile_id, 
584
        common_name, 
585
        ip4, 
586
        ip6, 
587
        connected_at, 
588
        disconnected_at
589
    FROM
590
        connection_log
591
    WHERE
592
        (ip4 = :ip_address OR ip6 = :ip_address)
593
    AND 
594
        connected_at < :date_time_unix
595
    AND 
596
        (disconnected_at > :date_time_unix OR disconnected_at IS NULL)
597
SQL
598
        );
599
        $stmt->bindValue(':ip_address', $ipAddress, PDO::PARAM_STR);
600
        $stmt->bindValue(':date_time_unix', $dateTimeUnix, PDO::PARAM_STR);
601
        $stmt->execute();
602
603
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
604
    }
605
606 View Code Duplication
    public function getTotpAttemptCount($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
607
    {
608
        $userId = $this->getId($userId);
609
        $stmt = $this->db->prepare(
610
<<< 'SQL'
611
        SELECT
612
            COUNT(*)
613
        FROM 
614
            totp_log
615
        WHERE user_id = :user_id
616
SQL
617
        );
618
619
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
620
        $stmt->execute();
621
622
        return (int) $stmt->fetchColumn();
623
    }
624
625
    public function recordTotpKey($userId, $totpKey, DateTime $dateTime)
626
    {
627
        $userId = $this->getId($userId);
628
        $stmt = $this->db->prepare(
629
<<< 'SQL'
630
    INSERT INTO totp_log 
631
        (user_id, totp_key, date_time)
632
    VALUES
633
        (:user_id, :totp_key, :date_time)
634
SQL
635
        );
636
637
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
638
        $stmt->bindValue(':totp_key', $totpKey, PDO::PARAM_STR);
639
        $stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR);
640
641
        try {
642
            $stmt->execute();
643
        } catch (PDOException $e) {
644
            // unable to record the TOTP, probably uniqueness contrains
645
            return false;
646
        }
647
648
        return true;
649
    }
650
651 View Code Duplication
    public function cleanConnectionLog(DateTime $dateTime)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
652
    {
653
        $stmt = $this->db->prepare(
654
<<< 'SQL'
655
    DELETE FROM
656
        connection_log
657
    WHERE
658
        connected_at < :date_time
659
    AND
660
        disconnected_at IS NOT NULL
661
SQL
662
        );
663
664
        $stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR);
665
666
        return $stmt->execute();
667
    }
668
669 View Code Duplication
    public function cleanUserMessages(DateTime $dateTime)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
670
    {
671
        $stmt = $this->db->prepare(
672
<<< 'SQL'
673
    DELETE FROM
674
        user_messages
675
    WHERE
676
        date_time < :date_time
677
SQL
678
        );
679
680
        $stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR);
681
682
        return $stmt->execute();
683
    }
684
685 View Code Duplication
    public function cleanTotpLog(DateTime $dateTime)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
686
    {
687
        $stmt = $this->db->prepare(
688
<<< 'SQL'
689
    DELETE FROM 
690
        totp_log
691
    WHERE 
692
        date_time < :date_time
693
SQL
694
        );
695
696
        $stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR);
697
698
        return $stmt->execute();
699
    }
700
701 View Code Duplication
    public function systemMessages($type)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
702
    {
703
        $stmt = $this->db->prepare(
704
<<< 'SQL'
705
    SELECT
706
        id, message, date_time 
707
    FROM 
708
        system_messages
709
    WHERE
710
        type = :type
711
SQL
712
        );
713
714
        $stmt->bindValue(':type', $type, PDO::PARAM_STR);
715
        $stmt->execute();
716
717
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
718
    }
719
720
    public function addSystemMessage($type, $message, DateTime $dateTime)
721
    {
722
        $stmt = $this->db->prepare(
723
<<< 'SQL'
724
    INSERT INTO system_messages 
725
        (type, message, date_time) 
726
    VALUES
727
        (:type, :message, :date_time)
728
SQL
729
        );
730
731
        $stmt->bindValue(':type', $type, PDO::PARAM_STR);
732
        $stmt->bindValue(':message', $message, PDO::PARAM_STR);
733
        $stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR);
734
        $stmt->execute();
735
736
        return 1 === $stmt->rowCount();
737
    }
738
739 View Code Duplication
    public function deleteSystemMessage($messageId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
740
    {
741
        $stmt = $this->db->prepare(
742
<<< 'SQL'
743
    DELETE FROM 
744
        system_messages
745
    WHERE id = :message_id
746
SQL
747
        );
748
749
        $stmt->bindValue(':message_id', $messageId, PDO::PARAM_INT);
750
        $stmt->execute();
751
752
        return 1 === $stmt->rowCount();
753
    }
754
755 View Code Duplication
    public function userMessages($userId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
756
    {
757
        $userId = $this->getId($userId);
758
759
        $stmt = $this->db->prepare(
760
<<< 'SQL'
761
    SELECT
762
        id, type, message, date_time 
763
    FROM 
764
        user_messages
765
    WHERE
766
        user_id = :user_id
767
    ORDER BY
768
        date_time DESC
769
SQL
770
        );
771
772
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
773
        $stmt->execute();
774
775
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
776
    }
777
778 View Code Duplication
    public function addUserMessage($userId, $type, $message, DateTime $dateTime)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
779
    {
780
        $userId = $this->getId($userId);
781
782
        $stmt = $this->db->prepare(
783
<<< 'SQL'
784
    INSERT INTO user_messages 
785
        (user_id, type, message, date_time) 
786
    VALUES
787
        (:user_id, :type, :message, :date_time)
788
SQL
789
        );
790
791
        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
792
        $stmt->bindValue(':type', $type, PDO::PARAM_STR);
793
        $stmt->bindValue(':message', $message, PDO::PARAM_STR);
794
        $stmt->bindValue(':date_time', $dateTime->format('Y-m-d H:i:s'), PDO::PARAM_STR);
795
        $stmt->execute();
796
797
        return 1 === $stmt->rowCount();
798
    }
799
800
    public function init()
801
    {
802
        $queryList = [];
803
        $queryList[] =
804
<<< 'SQL'
805
    CREATE TABLE IF NOT EXISTS users (
806
        id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
807
        user_id VARCHAR(255) NOT NULL UNIQUE,
808
        is_disabled BOOLEAN DEFAULT 0 NOT NULL
809
    )
810
SQL;
811
812
        $queryList[] =
813
<<< 'SQL'
814
    CREATE TABLE IF NOT EXISTS voot_tokens (
815
        voot_token VARCHAR(255) UNIQUE NOT NULL,
816
        user_id INTEGER UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE
817
    )
818
SQL;
819
820
        $queryList[] =
821
<<< 'SQL'
822
    CREATE TABLE IF NOT EXISTS totp_secrets (
823
        totp_secret VARCHAR(255) UNIQUE NOT NULL,
824
        user_id INTEGER UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE
825
    )
826
SQL;
827
828
        $queryList[] =
829
<<< 'SQL'
830
    CREATE TABLE IF NOT EXISTS certificates (
831
        common_name VARCHAR(255) UNIQUE NOT NULL,
832
        display_name VARCHAR(255) NOT NULL,
833
        valid_from DATETIME NOT NULL,
834
        valid_to DATETIME NOT NULL,
835
        is_disabled BOOLEAN DEFAULT 0,
836
        user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
837
    )
838
SQL;
839
840
        $queryList[] =
841
<<< 'SQL'
842
    CREATE TABLE IF NOT EXISTS totp_log (
843
        totp_key VARCHAR(255) NOT NULL,
844
        date_time DATETIME NOT NULL,
845
        user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
846
        UNIQUE (user_id, totp_key)
847
    )
848
SQL;
849
850
        $queryList[] =
851
<<< 'SQL'
852
    CREATE TABLE IF NOT EXISTS connection_log (
853
        user_id VARCHAR(255) NOT NULL,
854
        common_name VARCHAR(255) NOT NULL,
855
        profile_id VARCHAR(255) NOT NULL,
856
        ip4 VARCHAR(255) NOT NULL,
857
        ip6 VARCHAR(255) NOT NULL,
858
        connected_at DATETIME NOT NULL,
859
        disconnected_at DATETIME DEFAULT NULL,
860
        bytes_transferred INTEGER DEFAULT NULL                
861
    )
862
SQL;
863
864
        $queryList[] =
865
<<< 'SQL'
866
    CREATE TABLE IF NOT EXISTS system_messages (
867
        id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
868
        type VARCHAR(255) NOT NULL DEFAULT "notification",
869
        message TINYTEXT NOT NULL,
870
        date_time DATETIME NOT NULL
871
    )
872
SQL;
873
874
        $queryList[] =
875
<<< 'SQL'
876
    CREATE TABLE IF NOT EXISTS user_messages (
877
        id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
878
        type VARCHAR(255) NOT NULL DEFAULT "notification",
879
        message TINYTEXT NOT NULL,
880
        date_time DATETIME NOT NULL,
881
        user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
882
    )
883
SQL;
884
885
        foreach ($queryList as $query) {
886
            if ('sqlite' === $this->db->getAttribute(PDO::ATTR_DRIVER_NAME)) {
887
                $query = str_replace('AUTO_INCREMENT', 'AUTOINCREMENT', $query);
888
            }
889
            $this->db->query($query);
890
        }
891
    }
892
893
    public function drop()
894
    {
895
        $tableList = [
896
            'users',
897
            'voot_tokens',
898
            'totp_secrets',
899
            'certificates',
900
            'totp_log',
901
            'connection_log',
902
            'system_messages',
903
            'user_messages',
904
        ];
905
906
        foreach ($tableList as $table) {
907
            $this->db->query(sprintf('DROP TABLE IF EXISTS %s', $table));
908
        }
909
    }
910
}
911