1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Palladium\Mapper; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* SQL logic for authentication attempts using username/password |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
use Palladium\Component\DataMapper; |
10
|
|
|
use Palladium\Entity as Entity; |
11
|
|
|
use PDOStatement; |
12
|
|
|
use PDO; |
13
|
|
|
|
14
|
|
|
class StandardIdentity extends DataMapper |
15
|
|
|
{ |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @param Entity\StandardIdentity $entity |
19
|
|
|
*/ |
20
|
|
|
public function exists(Entity\StandardIdentity $entity) |
21
|
|
|
{ |
22
|
|
|
$sql = "SELECT 1 |
23
|
|
|
FROM {$this->table} |
24
|
|
|
WHERE type = :type |
25
|
|
|
AND fingerprint = :fingerprint |
26
|
|
|
AND identifier = :identifier |
27
|
|
|
AND (expires_on IS NULL OR expires_on > :now)"; |
28
|
|
|
|
29
|
|
|
$statement = $this->connection->prepare($sql); |
30
|
|
|
|
31
|
|
|
$statement->bindValue(':type', Entity\StandardIdentity::TYPE_EMAIL); |
32
|
|
|
$statement->bindValue(':fingerprint', $entity->getFingerprint()); |
33
|
|
|
$statement->bindValue(':identifier', $entity->getIdentifier()); |
34
|
|
|
$statement->bindValue(':now', time()); |
35
|
|
|
|
36
|
|
|
$statement->execute(); |
37
|
|
|
$data = $statement->fetch(PDO::FETCH_ASSOC); |
38
|
|
|
|
39
|
|
|
return empty($data) === false; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @param Entity\StandardIdentity $entity |
45
|
|
|
*/ |
46
|
|
|
public function fetch(Entity\StandardIdentity $entity) |
47
|
|
|
{ |
48
|
|
|
if ($entity->getId()) { |
49
|
|
|
$this->fetchById($entity); |
50
|
|
|
return; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
$this->fetchByIdentifier($entity); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
|
57
|
|
View Code Duplication |
private function fetchByIdentifier(Entity\StandardIdentity $entity) |
|
|
|
|
58
|
|
|
{ |
59
|
|
|
$sql = "SELECT identity_id AS id, |
60
|
|
|
account_id AS accountId, |
61
|
|
|
hash AS hash, |
62
|
|
|
status AS status, |
63
|
|
|
used_on AS lastUsed, |
64
|
|
|
token AS token, |
65
|
|
|
token_action AS tokenAction, |
66
|
|
|
token_expires_on AS tokenEndOfLife, |
67
|
|
|
token_payload AS tokenPayload |
68
|
|
|
FROM {$this->table} |
69
|
|
|
WHERE type = :type |
70
|
|
|
AND fingerprint = :fingerprint |
71
|
|
|
AND identifier = :identifier"; |
72
|
|
|
|
73
|
|
|
$statement = $this->connection->prepare($sql); |
74
|
|
|
|
75
|
|
|
$statement->bindValue(':type', $entity->getType()); |
76
|
|
|
$statement->bindValue(':identifier', $entity->getIdentifier()); |
77
|
|
|
$statement->bindValue(':fingerprint', $entity->getFingerprint()); |
78
|
|
|
|
79
|
|
|
$statement->execute(); |
80
|
|
|
|
81
|
|
|
$data = $statement->fetch(PDO::FETCH_ASSOC); |
82
|
|
|
|
83
|
|
|
if ($data) { |
84
|
|
|
if ($data['tokenPayload'] !== null) { |
85
|
|
|
$data['tokenPayload'] = json_decode($data['tokenPayload'], true); |
86
|
|
|
} |
87
|
|
|
$this->applyValues($entity, $data); |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
|
92
|
|
View Code Duplication |
private function fetchById(Entity\StandardIdentity $entity) |
|
|
|
|
93
|
|
|
{ |
94
|
|
|
$sql = "SELECT identity_id AS id, |
95
|
|
|
identifier AS identifier, |
96
|
|
|
account_id AS accountId, |
97
|
|
|
hash AS hash, |
98
|
|
|
status AS status, |
99
|
|
|
used_on AS lastUsed, |
100
|
|
|
token AS token, |
101
|
|
|
token_action AS tokenAction, |
102
|
|
|
token_expires_on AS tokenEndOfLife, |
103
|
|
|
token_payload AS tokenPayload |
104
|
|
|
FROM {$this->table} |
105
|
|
|
WHERE type = :type |
106
|
|
|
AND identity_id = :id"; |
107
|
|
|
|
108
|
|
|
$statement = $this->connection->prepare($sql); |
109
|
|
|
|
110
|
|
|
$statement->bindValue(':type', $entity->getType()); |
111
|
|
|
$statement->bindValue(':id', $entity->getId()); |
112
|
|
|
|
113
|
|
|
$statement->execute(); |
114
|
|
|
|
115
|
|
|
$data = $statement->fetch(PDO::FETCH_ASSOC); |
116
|
|
|
|
117
|
|
|
if ($data) { |
118
|
|
|
if ($data['tokenPayload'] !== null) { |
119
|
|
|
$data['tokenPayload'] = json_decode($data['tokenPayload'], true); |
120
|
|
|
} |
121
|
|
|
$this->applyValues($entity, $data); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @param Entity\StandardIdentity $entity |
128
|
|
|
*/ |
129
|
2 |
|
public function store(Entity\StandardIdentity $entity) |
130
|
|
|
{ |
131
|
2 |
|
if ($entity->getId() === null) { |
132
|
1 |
|
$this->createIdentity($entity); |
133
|
1 |
|
return; |
134
|
|
|
} |
135
|
|
|
|
136
|
1 |
|
$this->updateIdentity($entity); |
137
|
1 |
|
} |
138
|
|
|
|
139
|
|
|
|
140
|
1 |
|
private function createIdentity(Entity\StandardIdentity $entity) |
141
|
|
|
{ |
142
|
1 |
|
$sql = "INSERT INTO {$this->table} |
143
|
|
|
(type, status, identifier, fingerprint, hash, created_on, token, token_action, token_expires_on, token_payload) |
144
|
|
|
VALUES (:type, :status, :identifier, :fingerprint, :hash, :created, :token, :action, :token_eol, :payload)"; |
145
|
|
|
|
146
|
1 |
|
$statement = $this->connection->prepare($sql); |
147
|
|
|
|
148
|
1 |
|
$statement->bindValue(':type', Entity\StandardIdentity::TYPE_EMAIL); |
149
|
1 |
|
$statement->bindValue(':status', Entity\StandardIdentity::STATUS_NEW); |
150
|
1 |
|
$statement->bindValue(':identifier', $entity->getIdentifier()); |
151
|
1 |
|
$statement->bindValue(':fingerprint', $entity->getFingerprint()); |
152
|
1 |
|
$statement->bindValue(':hash', $entity->getHash()); |
153
|
1 |
|
$statement->bindValue(':created', time()); |
154
|
|
|
|
155
|
1 |
|
$this->bindToken($statement, $entity); |
156
|
|
|
|
157
|
1 |
|
$statement->execute(); |
158
|
|
|
|
159
|
1 |
|
$entity->setId($this->connection->lastInsertId()); |
160
|
1 |
|
} |
161
|
|
|
|
162
|
|
|
|
163
|
1 |
View Code Duplication |
private function updateIdentity(Entity\StandardIdentity $entity) |
|
|
|
|
164
|
|
|
{ |
165
|
1 |
|
$sql = "UPDATE {$this->table} |
166
|
|
|
SET hash = :hash, |
167
|
|
|
identifier = :identifier, |
168
|
|
|
fingerprint = :fingerprint, |
169
|
|
|
status = :status, |
170
|
|
|
used_on = :used, |
171
|
|
|
expires_on = :expires, |
172
|
|
|
token = :token, |
173
|
|
|
token_action = :action, |
174
|
|
|
token_expires_on = :token_eol, |
175
|
|
|
token_payload = :payload |
176
|
|
|
WHERE identity_id = :id"; |
177
|
|
|
|
178
|
1 |
|
$statement = $this->connection->prepare($sql); |
179
|
|
|
|
180
|
1 |
|
$statement->bindValue(':id', $entity->getId()); |
181
|
1 |
|
$statement->bindValue(':hash', $entity->getHash()); |
182
|
1 |
|
$statement->bindValue(':identifier', $entity->getIdentifier()); |
183
|
1 |
|
$statement->bindValue(':fingerprint', $entity->getFingerprint()); |
184
|
1 |
|
$statement->bindValue(':status', $entity->getStatus()); |
185
|
1 |
|
$statement->bindValue(':used', $entity->getLastUsed()); |
186
|
1 |
|
$statement->bindValue(':expires', $entity->getExpiresOn()); |
187
|
|
|
|
188
|
1 |
|
$this->bindToken($statement, $entity); |
189
|
|
|
|
190
|
1 |
|
$statement->execute(); |
191
|
1 |
|
} |
192
|
|
|
|
193
|
|
|
|
194
|
2 |
|
private function bindToken(PDOStatement $statement, Entity\StandardIdentity $entity) |
195
|
|
|
{ |
196
|
2 |
|
$statement->bindValue(':token', $entity->getToken()); |
197
|
2 |
|
$statement->bindValue(':action', $entity->getTokenAction()); |
198
|
2 |
|
$statement->bindValue(':token_eol', $entity->getTokenEndOfLife()); |
199
|
|
|
|
200
|
2 |
|
$payload = $entity->getTokenPayload(); |
201
|
2 |
|
if ($payload !== null) { |
202
|
|
|
$payload = json_encode($payload); |
203
|
|
|
} |
204
|
|
|
|
205
|
2 |
|
$statement->bindValue(':payload', $payload); |
206
|
2 |
|
} |
207
|
|
|
} |
208
|
|
|
|
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.