queryValue(' SELECT password_hash FROM users WHERE emailaddress = {string:emailaddress}', [ 'emailaddress' => $emailaddress, ]); // If there's no hash, the user likely does not exist. if (!$password_hash) return false; return password_verify($password, $password_hash); } public static function checkResetKey($id_user, $reset_key) { $key = Registry::get('db')->queryValue(' SELECT reset_key FROM users WHERE id_user = {int:id}', [ 'id' => $id_user, ]); return $key == $reset_key; } /** * Computes a password hash. */ public static function computeHash($password) { $hash = password_hash($password, PASSWORD_DEFAULT); if (!$hash) throw new Exception('Hash creation failed!'); return $hash; } public static function consumeResetKey($id_user) { return Registry::get('db')->query(' UPDATE users SET reset_key = NULL, reset_blocked_until = NULL WHERE id_user = {int:id_user}', ['id_user' => $id_user]); } public static function getResetTimeOut($id_user) { $resetTime = Registry::get('db')->queryValue(' SELECT reset_blocked_until FROM users WHERE id_user = {int:id_user}', ['id_user' => $id_user]); return max(0, $resetTime - time()); } /** * Verifies whether the user is currently logged in. */ public static function isLoggedIn() { if (!isset($_SESSION['user_id'])) return false; try { $exists = Member::fromId($_SESSION['user_id']); return true; } catch (NotFoundException $e) { return false; } } /** * Generates a new activation key. */ public static function newActivationKey() { $alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; $string = ''; for ($i = 0; $i < 16; $i++) $string .= $alpha[mt_rand(0, strlen($alpha) - 1)]; return $string; } public static function setResetKey($id_user) { return Registry::get('db')->query(' UPDATE users SET reset_key = {string:key}, reset_blocked_until = UNIX_TIMESTAMP() + ' . static::DEFAULT_RESET_TIMEOUT . ' WHERE id_user = {int:id}', [ 'id' => $id_user, 'key' => self::newActivationKey(), ]); } /** * Resets a password for a certain user. */ public static function updatePassword($id_user, $hash) { return Registry::get('db')->query(' UPDATE users SET password_hash = {string:hash}, reset_key = {string:blank} WHERE id_user = {int:id_user}', [ 'id_user' => $id_user, 'hash' => $hash, 'blank' => '', ]); } public static function updateResetTimeOut($id_user) { $currentResetTimeOut = static::getResetTimeOut($id_user); // New timeout: between 30 seconds, double the current timeout, and a full day $newResetTimeOut = min(max(static::DEFAULT_RESET_TIMEOUT, $currentResetTimeOut * 2), 60 * 60 * 24); $success = Registry::get('db')->query(' UPDATE users SET reset_blocked_until = {int:new_time_out} WHERE id_user = {int:id_user}', [ 'id_user' => $id_user, 'new_time_out' => time() + $newResetTimeOut, ]); if (!$success) throw new UnexpectedValueException('Could not set password reset timeout!'); return $newResetTimeOut; } }