Completed
Pull Request — master (#2)
by Tharanga
02:20
created

PdoThirdPartyStorageRepository::getByAppUser()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 4
nop 1
dl 0
loc 23
rs 9.7333
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 30-12-2018
5
 */
6
7
namespace TSK\SSO\Storage;
8
9
use TSK\SSO\AppUser\AppUser;
10
use TSK\SSO\Storage\Exception\DataCannotBeStoredException;
11
use TSK\SSO\ThirdParty\CommonAccessToken;
12
use TSK\SSO\ThirdParty\ThirdPartyUser;
13
use PDOException;
14
use PDO;
15
16
/**
17
 * @codeCoverageIgnore
18
 * @package TSK\SSO\Storage
19
 *
20
 * This will connect to a MySQL database using the php-pdo driver to persist vendor data.
21
 */
22
class PdoThirdPartyStorageRepository implements ThirdPartyStorageRepository
23
{
24
    /**
25
     * @var PDO
26
     */
27
    private $dbConnection;
28
29
    /**
30
     * @var string
31
     */
32
    private $table;
33
34
    /**
35
     * @param PDO $dbConnection
36
     * @param string $table name of the table in the MySQL database
37
     */
38
    public function __construct(PDO $dbConnection, $table = 'thirdparty_connections')
39
    {
40
        $this->dbConnection = $dbConnection;
41
        $this->table = $table;
42
    }
43
44
    /**
45
     * Returns a mapped full user record for a given vendor email address or null.
46
     *
47
     * @param string $emailAddress email address used within the given vendor system
48
     * @param string|null $vendorName [optional] name of the third party vendor for vendor filtering
49
     * @return MappedUser|null
50
     */
51
    public function getUser($emailAddress, $vendorName = null)
52
    {
53
        if (is_null($vendorName)) {
54
            $sql = "SELECT * FROM `{$this->table}` WHERE `vendor_email` = :email LIMIT 1";
55
            $stmt = $this->dbConnection->prepare($sql);
56
        } else {
57
            $sql = "SELECT * FROM `{$this->table}` WHERE `vendor_email` = :email AND `vendor_name` = :vendor LIMIT 1";
58
            $stmt = $this->dbConnection->prepare($sql);
59
            $stmt->bindParam(':vendor', $vendorName, PDO::PARAM_STR);
60
        }
61
62
        $stmt->bindParam(':email', $emailAddress, PDO::PARAM_STR);
63
        $stmt->execute();
64
65
        $userMap = $stmt->fetch(PDO::FETCH_ASSOC);
66
        if (empty($userMap)) {
67
            return null;
68
        }
69
70
        return new MappedUser(
71
            $userMap['app_user_id'],
72
            $userMap['vendor_name'],
73
            $userMap['vendor_email'],
74
            $userMap['vendor_access_token'],
75
            $userMap['vendor_data']
76
        );
77
    }
78
79
    /**
80
     * Returns any vendor MappedUser list for a given Application user.
81
     *
82
     * @param AppUser $appUser
83
     * @return MappedUser[]
84
     */
85
    public function getByAppUser(AppUser $appUser)
86
    {
87
        $stmt = $this->dbConnection->prepare("SELECT * FROM `{$this->table}` WHERE `app_user_id` = :appUserId");
88
        $appUserId = $appUser->id();
89
        if (is_numeric($appUserId)) {
90
            $stmt->bindParam(':appUserId', $appUserId, PDO::PARAM_INT);
91
        } else {
92
            $stmt->bindParam(':appUserId', $appUserId, PDO::PARAM_STR);
93
        }
94
        $stmt->execute();
95
96
        $connections = array();
97
        while ($mappedUser = $stmt->fetch(PDO::FETCH_ASSOC)) {
98
            $connections[] = new MappedUser(
99
                $mappedUser['app_user_id'],
100
                $mappedUser['vendor_name'],
101
                $mappedUser['vendor_email'],
102
                $mappedUser['vendor_access_token'],
103
                $mappedUser['vendor_data']
104
            );
105
        }
106
107
        return $connections;
108
    }
109
110
    /**
111
     * @param AppUser $appUser
112
     * @param ThirdPartyUser $thirdPartyUser
113
     * @param CommonAccessToken $accessToken
114
     * @throws DataCannotBeStoredException
115
     */
116
    public function save(
117
        AppUser $appUser,
118
        ThirdPartyUser $thirdPartyUser,
119
        CommonAccessToken $accessToken
120
    ) {
121
        $sql = <<<SQL
122
INSERT INTO `{$this->table}`
123
(
124
    `app_user_id`,
125
    `vendor_name`,
126
    `vendor_email`,
127
    `vendor_access_token`,
128
    `vendor_data`,
129
    `created_at`
130
)
131
VALUES
132
(
133
    :appUserId,
134
    :vendorName,
135
    :vendorEmail,
136
    :vendorToken,
137
    :vendorData,
138
    NOW()
139
)
140
ON DUPLICATE KEY UPDATE
141
    `vendor_access_token` = VALUES(`vendor_access_token`),
142
    `vendor_data` = VALUES(`vendor_data`),
143
    `updated_at` = NOW()
144
SQL;
145
        try {
146
            $vendorData = json_encode($thirdPartyUser->toArray());
147
            $appUserId = $appUser->id();
148
            $vendorName = $accessToken->vendor();
149
            $vendorEmail = $thirdPartyUser->email();
150
            $vendorToken = $accessToken->token();
151
152
            $stmt = $this->dbConnection->prepare($sql);
153
            $stmt->bindParam(':appUserId', $appUserId, PDO::PARAM_STR);
154
            $stmt->bindParam(':vendorName', $vendorName, PDO::PARAM_STR);
155
            $stmt->bindParam(':vendorEmail', $vendorEmail, PDO::PARAM_STR);
156
            $stmt->bindParam(':vendorToken', $vendorToken, PDO::PARAM_STR);
157
            $stmt->bindParam(':vendorData', $vendorData, PDO::PARAM_STR);
158
            $stmt->execute();
159
        } catch (PDOException $ex) {
160
            throw new DataCannotBeStoredException(
161
                sprintf("Couldn't save the third party user data. Error : %s", $ex->getMessage()),
162
                $ex->getCode(),
163
                $ex
164
            );
165
        }
166
    }
167
168
    /**
169
     * Use this to clean the storage after revoking access to a third party for example.
170
     *
171
     * @param string $emailAddress email address used within the given vendor system
172
     * @param string $vendorName name of the third party where the given email belongs to
173
     * @return bool
174
     */
175
    public function remove($emailAddress, $vendorName)
176
    {
177
        $sql = "DELETE FROM `{$this->table}` WHERE `vendor_email` = :email AND `vendor_name` = :vendor LIMIT 1";
178
        $stmt = $this->dbConnection->prepare($sql);
179
        $stmt->bindParam(':email', $emailAddress, PDO::PARAM_STR);
180
        $stmt->bindParam(':vendor', $vendorName, PDO::PARAM_STR);
181
        return $stmt->execute();
182
    }
183
}
184