Skip to content

Commit 35366f7

Browse files
committed
Move verification token to mysql
1 parent fde3136 commit 35366f7

File tree

4 files changed

+31
-114
lines changed

4 files changed

+31
-114
lines changed

src/controllers/User/Register.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ protected function tryRegister(Router &$router, UserRegisterModel &$model) {
209209

210210
$state->mail = &$mail;
211211
$state->name = ( $user ? $user->getName() : $username );
212-
$state->token = ( $user ? $user->getVerificationToken() : null );
212+
$state->token = ( $user ? $user->getVerifierToken() : null );
213213
$state->user_id = $user_id;
214214

215215
try {

src/controllers/User/ResetPassword.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ protected function doPasswordReset( UserResetPasswordModel &$model, &$data ) {
9292
$mail_config = Common::$config->email;
9393

9494
$state->mail = &$mail;
95-
$state->token = $model->user->getVerificationToken();
95+
$state->token = $model->user->getVerifierToken();
9696
$state->user = $model->user;
9797

9898
try {
@@ -163,7 +163,7 @@ protected function doPasswordReset( UserResetPasswordModel &$model, &$data ) {
163163
return self::RET_EMAIL;
164164
}
165165

166-
if ( $model->token !== $model->user->getVerificationToken() ) {
166+
if ( $model->token !== $model->user->getVerifierToken() ) {
167167
$model->error = 'INVALID_TOKEN';
168168
return self::RET_FAILURE;
169169
}

src/controllers/User/Verify.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function &run( Router &$router, View &$view, array &$args ) {
3939
}
4040

4141
if ( $model->user ) {
42-
$user_token = $model->user->getVerificationToken();
42+
$user_token = $model->user->getVerifierToken();
4343

4444
if ( $user_token === $model->token ) {
4545
$model->user->invalidateVerificationToken();

src/libraries/User.php

Lines changed: 27 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ class User implements JsonSerializable {
4545
const OPTION_ACL_USER_MODIFY = 0x00200000;
4646
const OPTION_ACL_USER_DELETE = 0x00400000;
4747

48-
const VERIFICATION_TOKEN_TTL = 86400;
49-
5048
protected $created_datetime;
5149
protected $display_name;
5250
protected $email;
@@ -70,6 +68,7 @@ public function __construct($data) {
7068
$this->timezone = null;
7169
$this->username = null;
7270
$this->verified_datetime = null;
71+
$this->verifier_token = null;
7372
$this->refresh();
7473
} else if ($data instanceof StdClass) {
7574
self::normalize($data);
@@ -83,6 +82,7 @@ public function __construct($data) {
8382
$this->timezone = $data->timezone;
8483
$this->username = $data->username;
8584
$this->verified_datetime = $data->verified_datetime;
85+
$this->verifier_token = $data->verifier_token;
8686
} else {
8787
throw new InvalidArgumentException("Cannot use data argument");
8888
}
@@ -111,14 +111,6 @@ public function changeDisplayName($new_display_name) {
111111
} else {
112112
$this->display_name = (string) $new_display_name;
113113
}
114-
$key = 'bnetdocs-user-' . $this->id;
115-
$obj = Common::$cache->get($key);
116-
if ($obj !== false) {
117-
$obj = unserialize($obj);
118-
$obj->display_name = $this->display_name;
119-
$obj = serialize($obj);
120-
Common::$cache->set($key, $obj, 300);
121-
}
122114
}
123115
} catch (PDOException $e) {
124116
throw new QueryException('Cannot change user display name', $e);
@@ -142,14 +134,6 @@ public function changeEmail($new_email) {
142134
$stmt->closeCursor();
143135
if ($successful) {
144136
$this->email = (string) $new_email;
145-
$key = 'bnetdocs-user-' . $this->id;
146-
$obj = Common::$cache->get($key);
147-
if ($obj !== false) {
148-
$obj = unserialize($obj);
149-
$obj->email = $this->email;
150-
$obj = serialize($obj);
151-
Common::$cache->set($key, $obj, 300);
152-
}
153137
}
154138
} catch (PDOException $e) {
155139
throw new QueryException('Cannot change user email', $e);
@@ -176,15 +160,6 @@ public function changePassword($new_password) {
176160
$stmt->closeCursor();
177161
if ($successful) {
178162
$this->password_hash = (string) $password_hash;
179-
$key = "bnetdocs-user-" . $this->id;
180-
$obj = Common::$cache->get($key);
181-
if ($obj !== false) {
182-
$obj = unserialize($obj);
183-
$obj->password_hash = $this->password_hash;
184-
$obj->password_salt = null;
185-
$obj = serialize($obj);
186-
Common::$cache->set($key, $obj, 300);
187-
}
188163
}
189164
} catch (PDOException $e) {
190165
throw new QueryException("Cannot change user password", $e);
@@ -208,14 +183,6 @@ public function changeUsername($new_username) {
208183
$stmt->closeCursor();
209184
if ($successful) {
210185
$this->username = (string) $new_username;
211-
$key = 'bnetdocs-user-' . $this->id;
212-
$obj = Common::$cache->get($key);
213-
if ($obj !== false) {
214-
$obj = unserialize($obj);
215-
$obj->username = $this->username;
216-
$obj = serialize($obj);
217-
Common::$cache->set($key, $obj, 300);
218-
}
219186
}
220187
} catch (PDOException $e) {
221188
throw new QueryException('Cannot change username of user', $e);
@@ -258,27 +225,28 @@ public static function create(
258225
if (!isset(Common::$database)) {
259226
Common::$database = DatabaseDriver::getDatabaseObject();
260227
}
228+
$verifier_token = self::generateVerifierToken($username, $email);
261229
$password_hash = self::createPassword($password);
262230
$successful = false;
263231
try {
264232
$stmt = Common::$database->prepare("
265233
INSERT INTO `users` (
266234
`id`, `email`, `username`, `display_name`, `created_datetime`,
267-
`verified_datetime`, `password_hash`, `password_salt`,
268-
`options_bitmask`, `timezone`
235+
`verified_datetime`, `verifier_token`, `password_hash`,
236+
`password_salt`, `options_bitmask`, `timezone`
269237
) VALUES (
270238
NULL, :email, :username, :display_name, NOW(),
271-
NULL, :password_hash, NULL, :options_bitmask, NULL
239+
NULL, :verifier, :password_hash, NULL, :options_bitmask, NULL
272240
);
273241
");
274242
$stmt->bindParam(":email", $email, PDO::PARAM_STR);
275243
$stmt->bindParam(":username", $username, PDO::PARAM_STR);
276244
$stmt->bindParam(":display_name", $display_name, PDO::PARAM_STR);
245+
$stmt->bindParam(":verifier", $verifier_token, PDO::PARAM_STR);
277246
$stmt->bindParam(":password_hash", $password_hash, PDO::PARAM_STR);
278247
$stmt->bindParam(":options_bitmask", $options_bitmask, PDO::PARAM_INT);
279248
$successful = $stmt->execute();
280249
$stmt->closeCursor();
281-
Common::$cache->delete('bnetdocs-users');
282250
} catch (PDOException $e) {
283251
throw new QueryException("Cannot create user", $e);
284252
} finally {
@@ -343,6 +311,12 @@ public static function findIdByUsername($username) {
343311
return null;
344312
}
345313

314+
public static function generateVerifierToken($username, $email) {
315+
// entropy
316+
$digest = sprintf('%s%s%s', mt_rand(), $username, $email);
317+
return hash('sha256', $digest);
318+
}
319+
346320
public function getAcl($acl) {
347321
return ($this->options_bitmask & $acl);
348322
}
@@ -367,18 +341,6 @@ public static function &getAllUsers(
367341
} else {
368342
$limit_clause = 'LIMIT ' . (int) $index . ',' . (int) $limit;
369343
}
370-
if (empty($limit_clause)) {
371-
$cache_key = 'bnetdocs-users';
372-
$cache_val = Common::$cache->get($cache_key);
373-
if ($cache_val !== false && !empty($cache_val)) {
374-
$ids = explode(',', $cache_val);
375-
$objects = [];
376-
foreach ($ids as $id) {
377-
$objects[] = new self($id);
378-
}
379-
return $objects;
380-
}
381-
}
382344
if (!isset(Common::$database)) {
383345
Common::$database = DatabaseDriver::getDatabaseObject();
384346
}
@@ -394,7 +356,8 @@ public static function &getAllUsers(
394356
`password_salt`,
395357
`timezone`,
396358
`username`,
397-
`verified_datetime`
359+
`verified_datetime`,
360+
`verifier_token`
398361
FROM `users`
399362
ORDER BY
400363
' . ($order ? '`' . $order[0] . '` ' . $order[1] . ',' : '') . '
@@ -403,19 +366,11 @@ public static function &getAllUsers(
403366
if (!$stmt->execute()) {
404367
throw new QueryException('Cannot refresh all users');
405368
}
406-
$ids = [];
407369
$objects = [];
408370
while ($row = $stmt->fetch(PDO::FETCH_OBJ)) {
409-
$ids[] = (int) $row->id;
410371
$objects[] = new self($row);
411-
Common::$cache->set(
412-
'bnetdocs-user-' . $row->id, serialize($row), 300
413-
);
414372
}
415373
$stmt->closeCursor();
416-
if (empty($limit_clause)) {
417-
Common::$cache->set($cache_key, implode(',', $ids), 300);
418-
}
419374
return $objects;
420375
} catch (PDOException $e) {
421376
throw new QueryException('Cannot refresh all users', $e);
@@ -505,23 +460,6 @@ public function getUsername() {
505460
return $this->username;
506461
}
507462

508-
public function getVerificationToken() {
509-
$key = 'bnetdocs-userverify-' . $this->id;
510-
$value = Common::$cache->get($key);
511-
512-
if ($value === false) {
513-
$gmp = gmp_init(time());
514-
$gmp = gmp_mul($gmp, mt_rand());
515-
$gmp = gmp_mul($gmp, gmp_random_bits(64));
516-
517-
$value = hash('sha256', gmp_strval($gmp, 36));
518-
519-
Common::$cache->set($key, $value, self::VERIFICATION_TOKEN_TTL);
520-
}
521-
522-
return $value;
523-
}
524-
525463
public function getVerifiedDateTime() {
526464
if (is_null($this->verified_datetime)) {
527465
return $this->verified_datetime;
@@ -533,9 +471,8 @@ public function getVerifiedDateTime() {
533471
}
534472
}
535473

536-
public function invalidateVerificationToken() {
537-
$key = 'bnetdocs-userverify-' . $this->id;
538-
return Common::$cache->delete($key);
474+
public function getVerifierToken() {
475+
return $this->verifier_token;
539476
}
540477

541478
public function isDisabled() {
@@ -622,25 +559,13 @@ protected static function normalize(StdClass &$data) {
622559
if (!is_null($data->verified_datetime))
623560
$data->verified_datetime = (string) $data->verified_datetime;
624561

562+
if (!is_null($data->verifier_token))
563+
$data->verifier_token = (string) $data->verifier_token;
564+
625565
return true;
626566
}
627567

628568
public function refresh() {
629-
$cache_key = "bnetdocs-user-" . $this->id;
630-
$cache_val = Common::$cache->get($cache_key);
631-
if ($cache_val !== false) {
632-
$cache_val = unserialize($cache_val);
633-
$this->created_datetime = $cache_val->created_datetime;
634-
$this->display_name = $cache_val->display_name;
635-
$this->email = $cache_val->email;
636-
$this->options_bitmask = $cache_val->options_bitmask;
637-
$this->password_hash = $cache_val->password_hash;
638-
$this->password_salt = $cache_val->password_salt;
639-
$this->timezone = $cache_val->timezone;
640-
$this->username = $cache_val->username;
641-
$this->verified_datetime = $cache_val->verified_datetime;
642-
return true;
643-
}
644569
if (!isset(Common::$database)) {
645570
Common::$database = DatabaseDriver::getDatabaseObject();
646571
}
@@ -656,7 +581,8 @@ public function refresh() {
656581
`password_salt`,
657582
`timezone`,
658583
`username`,
659-
`verified_datetime`
584+
`verified_datetime`,
585+
`verifier_token`
660586
FROM `users`
661587
WHERE `id` = :id
662588
LIMIT 1;
@@ -679,7 +605,7 @@ public function refresh() {
679605
$this->timezone = $row->timezone;
680606
$this->username = $row->username;
681607
$this->verified_datetime = $row->verified_datetime;
682-
Common::$cache->set($cache_key, serialize($row), 300);
608+
$this->verifier_token = $row->verifier_token;
683609
return true;
684610
} catch (PDOException $e) {
685611
throw new QueryException("Cannot refresh user", $e);
@@ -716,7 +642,8 @@ public function setVerified() {
716642
$stmt = Common::$database->prepare('
717643
UPDATE `users` SET
718644
`options_bitmask` = :bits,
719-
`verified_datetime` = :dt
645+
`verified_datetime` = :dt,
646+
`verifier_token` = NULL
720647
WHERE `id` = :user_id;
721648
');
722649
$dt = $verified_datetime->format( 'Y-m-d H:i:s' );
@@ -726,23 +653,13 @@ public function setVerified() {
726653
$successful = $stmt->execute();
727654
$stmt->closeCursor();
728655
if ($successful) {
729-
$this->verified_datetime = $verified_datetime;
730656
$this->options_bitmask = $options_bitmask;
731-
$key = 'bnetdocs-user-' . $this->id;
732-
$obj = Common::$cache->get($key);
733-
if ($obj !== false) {
734-
$obj = unserialize($obj);
735-
$obj->verified_datetime = $this->verified_datetime;
736-
$obj->options_bitmask = $this->options_bitmask;
737-
$obj = serialize($obj);
738-
Common::$cache->set($key, $obj, 300);
739-
}
657+
$this->verified_datetime = $verified_datetime;
658+
$this->verifier_token = null;
740659
}
741660

742661
} catch (PDOException $e) {
743-
744662
throw new QueryException('Cannot set user as verified', $e);
745-
746663
} finally {
747664
return $successful;
748665
}

0 commit comments

Comments
 (0)