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