Passed
Push — master ( 35fb8a...2dccb2 )
by Pieter van der
05:32 queued 14s
created

Tiqr_UserSecretStorage_Pdo   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Test Coverage

Coverage 75.68%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 10
eloc 41
c 2
b 0
f 0
dl 0
loc 108
ccs 28
cts 37
cp 0.7568
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A userExists() 0 10 2
A getUserSecret() 0 22 4
A __construct() 0 10 1
A setUserSecret() 0 25 3
1
<?php
2
/**
3
 * This file is part of the tiqr project.
4
 * 
5
 * The tiqr project aims to provide an open implementation for 
6
 * authentication using mobile devices. It was initiated by 
7
 * SURFnet and developed by Egeniq.
8
 *
9
 * More information: http://www.tiqr.org
10
 *
11
 * @author Patrick Honing <[email protected]>
12
 * 
13
 * @package tiqr
14
 *
15
 * @license New BSD License - See LICENSE file for details.
16
 *
17
 * @copyright (C) 2010-2012 SURFnet BV
18
 * 
19
 * Create SQL table (MySQL):
20
 * CREATE TABLE `tiqrusersecret` (`userid` varchar(10) PRIMARY KEY, `secret` varchar(100))
21
 * 
22
 */
23
24 1
require_once 'Tiqr/UserSecretStorage/UserSecretStorageTrait.php';
25
26
use Psr\Log\LoggerInterface;
27
28
/**
29
 * This user storage implementation implements a user secret storage using PDO.
30
 * It is usable for any database with a PDO driver
31
 * 
32
 * @author Patrick Honing <[email protected]>
33
 *
34
 * You can create separate tables for Tiqr_UserSecretStorage_Pdo and Tiqr_UserStorage_Pdo
35
 * You can also combine the two tables by adding a "secret" column to the user storage table
36
 * @see Tiqr_UserStorage_Pdo
37
 *
38
 * Mysql Create statement usersecret table
39
40
CREATE TABLE IF NOT EXISTS usersecret (
41
    id integer NOT NULL PRIMARY KEY AUTO_INCREMENT,
42
    userid varchar(30) NOT NULL UNIQUE,
43
    secret varchar(128),
44
);
45
 *
46
 */
47
48
class Tiqr_UserSecretStorage_Pdo implements Tiqr_UserSecretStorage_Interface
49
{
50
    use UserSecretStorageTrait;
51
52
    private $tableName;
53
54
    private $handle;
55
56
    /**
57
     * @var LoggerInterface
58
     */
59
    private $logger;
60
61
    /**
62
     * @param Tiqr_UserSecretStorage_Encryption_Interface $encryption
63
     * @param LoggerInterface $logger
64
     * @param PDO $handle
65
     */
66 6
    public function __construct(
67
        Tiqr_UserSecretStorage_Encryption_Interface $encryption,
68
        LoggerInterface $logger,
69
        PDO $handle,
70
        string $tableName
71
    ) {
72 6
        $this->encryption = $encryption;
73 6
        $this->logger = $logger;
74 6
        $this->handle = $handle;
75 6
        $this->tableName = $tableName;
76 6
    }
77
78
    /**
79
     * @see Tiqr_UserSecretStorage_Interface::userExists()
80
     *
81
     * Note: duplicate of Tiqr_UserStorage_Pdo::userExists()
82
     */
83 2
    public function userExists(string $userId): bool
84
    {
85
        try {
86 2
            $sth = $this->handle->prepare('SELECT userid FROM ' . $this->tableName . ' WHERE userid = ?');
87 2
            $sth->execute(array($userId));
88 2
            return (false !== $sth->fetchColumn());
89
        }
90
        catch (Exception $e) {
91
            $this->logger->error('PDO error checking user exists', array('exception'=>$e, 'userId'=>$userId));
92
            throw ReadWriteException::fromOriginalException($e);
93
        }
94
    }
95
96
    /**
97
     * Get the user's secret
98
     *
99
     * @param String $userId
100
     * @return string
101
     * @throws Exception
102
     */
103 1
    private function getUserSecret(string $userId): string
0 ignored issues
show
Unused Code introduced by
The method getUserSecret() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
104
    {
105
        try {
106 1
            $sth = $this->handle->prepare('SELECT secret FROM ' . $this->tableName . ' WHERE userid = ?');
107 1
            $sth->execute(array($userId));
108 1
            $res=$sth->fetchColumn();
109 1
            if ($res === false) {
110
                // No result
111
                $this->logger->error(sprintf('No result getting secret for user "%s"', $userId));
112 1
                throw new RuntimeException('User not found');
113
            }
114
        }
115
        catch (Exception $e) {
116
            $this->logger->error('PDO error getting user', array('exception' => $e, 'userId' => $userId));
117
            throw ReadWriteException::fromOriginalException($e);
118
        }
119
120 1
        if (!is_string($res)) {
121
            $this->logger->error(sprintf('No secret found for user "%s"', $userId));
122
            throw new RuntimeException('Secret not found');
123
        }
124 1
        return $res;
125
    }
126
127
    /**
128
     *
129
     * @throws Exception
130
     */
131 2
    private function setUserSecret(string $userId, string $secret): void
0 ignored issues
show
Unused Code introduced by
The method setUserSecret() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
132
    {
133
        // UserSecretStorage can be used in a separate table. In this case the table has its own userid column
134
        // This means that when a user has been created using in the UserStorage, it does not exists in the
135
        // UserSecretStorage so userExists will be false and we need to use an INSERT query.
136
137
        // It is also possible to use one table for both the UserStorage and the UserSecretStorage, in that case the
138
        // userid column is shared between the UserStorage and UserSecretStorage and the user must first have been created
139
        // in the UserStorage because:
140
        // - UserStorage_Pdo::create() no longer supports overwriting an existing user
141
        // - The INSERT will fail when displayname has a NOT NULL constraint
142
        try {
143 2
            if ($this->userExists($userId)) {
144 1
                $sth = $this->handle->prepare('UPDATE ' . $this->tableName . ' SET secret = ? WHERE userid = ?');
145
            } else {
146 1
                $sth = $this->handle->prepare('INSERT INTO ' . $this->tableName . ' (secret,userid) VALUES (?,?)');
147
            }
148 2
            $sth->execute(array($secret, $userId));
149
        }
150 1
        catch (Exception $e) {
151 1
            $this->logger->error(
152 1
                sprintf('Unable to persist user secret for user "%s" in user secret storage (PDO)', $userId),
153 1
                array('exception'=>$e)
154
            );
155 1
            throw ReadWriteException::fromOriginalException($e);
156
        }
157 1
    }
158
}
159