Passed
Push — develop ( 8984a1...fa7884 )
by Pieter van der
01:36 queued 14s
created

Tiqr_UserSecretStorage_Pdo   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Test Coverage

Coverage 76.32%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 10
eloc 41
c 2
b 0
f 0
dl 0
loc 108
ccs 29
cts 38
cp 0.7632
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A userExists() 0 10 2
A getUserSecret() 0 22 4
A setUserSecret() 0 25 3
A __construct() 0 15 1
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
use Psr\Log\LoggerInterface;
25
26
/**
27
 * This user storage implementation implements a user secret storage using PDO.
28
 * It is usable for any database with a PDO driver
29
 * 
30
 * @author Patrick Honing <[email protected]>
31
 *
32
 * You can create separate tables for Tiqr_UserSecretStorage_Pdo and Tiqr_UserStorage_Pdo
33
 * You can also combine the two tables by adding a "secret" column to the user storage table
34
 * @see Tiqr_UserStorage_Pdo
35
 *
36
 * Mysql Create statement usersecret table
37
38
CREATE TABLE IF NOT EXISTS usersecret (
39
    id integer NOT NULL PRIMARY KEY AUTO_INCREMENT,
40
    userid varchar(30) NOT NULL UNIQUE,
41
    secret varchar(128),
42
);
43
44
 * @see Tiqr_UserSecretStorage::getSecretStorage()
45
 * @see Tiqr_UserSecretStorage_Interface
46
 *
47
 * Supported options:
48
 * path : Path to the directory where the user data is stored
49
 * Supported options:
50
 * table    : The name of the user table in the database. Optional. Defaults to "tiqrusersecret".
51
 * dsn      : The dsn, see the PDO interface documentation
52
 * username : The database username
53
 * password : The database password
54
 *
55
 */
56
57
class Tiqr_UserSecretStorage_Pdo implements Tiqr_UserSecretStorage_Interface
58
{
59
    use UserSecretStorageTrait;
60
61
    private $tableName;
62
63
    private $handle;
64
65
    /**
66
     * @param Tiqr_UserSecretStorage_Encryption_Interface $encryption
67
     * @param LoggerInterface $logger
68
     * @param PDO $handle
69
     */
70 9
    public function __construct(
71
        Tiqr_UserSecretStorage_Encryption_Interface $encryption,
72
        LoggerInterface $logger,
73
        PDO $handle,
74
        string $tableName,
75
        array $decryption = array()
76
    ) {
77
        // See UserSecretStorageTrait
78 9
        $this->encryption = $encryption;
79 9
        $this->logger = $logger;
80 9
        $this->decryption = $decryption;
81
82
        // Set our own properties
83 9
        $this->handle = $handle;
84 9
        $this->tableName = $tableName;
85 9
    }
86
87
    /**
88
     * @see Tiqr_UserSecretStorage_Interface::userExists()
89
     *
90
     * Note: duplicate of Tiqr_UserStorage_Pdo::userExists()
91
     */
92 5
    public function userExists(string $userId): bool
93
    {
94
        try {
95 5
            $sth = $this->handle->prepare('SELECT userid FROM ' . $this->tableName . ' WHERE userid = ?');
96 5
            $sth->execute(array($userId));
97 5
            return (false !== $sth->fetchColumn());
98
        }
99
        catch (Exception $e) {
100
            $this->logger->error('PDO error checking user exists', array('exception'=>$e, 'userId'=>$userId));
101
            throw ReadWriteException::fromOriginalException($e);
102
        }
103
    }
104
105
    /**
106
     * Get the user's secret
107
     *
108
     * @param String $userId
109
     * @return string
110
     * @throws Exception
111
     */
112 3
    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...
113
    {
114
        try {
115 3
            $sth = $this->handle->prepare('SELECT secret FROM ' . $this->tableName . ' WHERE userid = ?');
116 3
            $sth->execute(array($userId));
117 3
            $res=$sth->fetchColumn();
118 3
            if ($res === false) {
119
                // No result
120
                $this->logger->error(sprintf('No result getting secret for user "%s"', $userId));
121 3
                throw new RuntimeException('User not found');
122
            }
123
        }
124
        catch (Exception $e) {
125
            $this->logger->error('PDO error getting user', array('exception' => $e, 'userId' => $userId));
126
            throw ReadWriteException::fromOriginalException($e);
127
        }
128
129 3
        if (!is_string($res)) {
130
            $this->logger->error(sprintf('No secret found for user "%s"', $userId));
131
            throw new RuntimeException('Secret not found');
132
        }
133 3
        return $res;
134
    }
135
136
    /**
137
     *
138
     * @throws Exception
139
     */
140 5
    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...
141
    {
142
        // UserSecretStorage can be used in a separate table. In this case the table has its own userid column
143
        // This means that when a user has been created using in the UserStorage, it does not exists in the
144
        // UserSecretStorage so userExists will be false and we need to use an INSERT query.
145
146
        // It is also possible to use one table for both the UserStorage and the UserSecretStorage, in that case the
147
        // userid column is shared between the UserStorage and UserSecretStorage and the user must first have been created
148
        // in the UserStorage because:
149
        // - UserStorage_Pdo::create() no longer supports overwriting an existing user
150
        // - The INSERT will fail when displayname has a NOT NULL constraint
151
        try {
152 5
            if ($this->userExists($userId)) {
153 2
                $sth = $this->handle->prepare('UPDATE ' . $this->tableName . ' SET secret = ? WHERE userid = ?');
154
            } else {
155 3
                $sth = $this->handle->prepare('INSERT INTO ' . $this->tableName . ' (secret,userid) VALUES (?,?)');
156
            }
157 4
            $sth->execute(array($secret, $userId));
158
        }
159 2
        catch (Exception $e) {
160 2
            $this->logger->error(
161 2
                sprintf('Unable to persist user secret for user "%s" in user secret storage (PDO)', $userId),
162 2
                array('exception'=>$e)
163
            );
164 2
            throw ReadWriteException::fromOriginalException($e);
165
        }
166 3
    }
167
}
168