View source
<?php
namespace Drupal\persistent_login;
use DateTime;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Access\CsrfTokenGenerator;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\user\UserInterface;
use Psr\Log\LoggerInterface;
class TokenManager {
protected $configFactory;
protected $connection;
protected $csrfToken;
protected $logger;
protected $time;
public function __construct(Connection $connection, ConfigFactoryInterface $configFactory, CsrfTokenGenerator $csrfToken, LoggerInterface $logger, TimeInterface $time) {
$this->configFactory = $configFactory;
$this->connection = $connection;
$this->csrfToken = $csrfToken;
$this->logger = $logger;
$this->time = $time;
}
public function validateToken(PersistentToken $token) {
$selectResult = $this->connection
->select('persistent_login', 'pl')
->fields('pl', [
'uid',
'created',
'refreshed',
'expires',
])
->condition('expires', $this->time
->getRequestTime(), '>')
->condition('series', $token
->getSeries())
->condition('instance', $token
->getInstance())
->execute();
if ($tokenData = $selectResult
->fetchObject()) {
return $token
->setUid($tokenData->uid)
->setCreated(new DateTime('@' . $tokenData->created))
->setRefreshed(new DateTime('@' . $tokenData->refreshed))
->setExpiry(new DateTime('@' . $tokenData->expires));
}
else {
return $token
->setInvalid();
}
}
public function createNewTokenForUser($uid) {
$config = $this->configFactory
->get('persistent_login.settings');
$token = new PersistentToken($this->csrfToken
->get(Crypt::randomBytesBase64()), $this->csrfToken
->get(Crypt::randomBytesBase64()), $uid);
if ($config
->get('lifetime') === 0) {
$token
->setExpiry(new DateTime("@" . 2147483647));
}
else {
$token
->setExpiry(new DateTime("now +" . $config
->get('lifetime') . " day"));
}
try {
$this->connection
->insert('persistent_login')
->fields([
'uid' => $uid,
'series' => $token
->getSeries(),
'instance' => $token
->getInstance(),
'created' => $token
->getCreated()
->getTimestamp(),
'refreshed' => $token
->getRefreshed()
->getTimestamp(),
'expires' => $token
->getExpiry()
->getTimestamp(),
])
->execute();
} catch (\Exception $e) {
throw new TokenException("An error occurred storing the new token", 0, $e);
}
if ($config
->get('max_tokens') !== 0) {
try {
$oldTokensResult = $this->connection
->select('persistent_login', 'pl')
->fields('pl', [
'created',
'expires',
])
->orderBy('expires', 'DESC')
->orderBy('created', 'DESC')
->condition('uid', $uid)
->range($config
->get('max_tokens'), 1)
->execute();
if ($oldestToken = $oldTokensResult
->fetchObject()) {
$this->connection
->delete('persistent_login')
->condition('uid', $uid)
->condition('expires', $oldestToken->expires, '<=')
->condition('created', $oldestToken->created, '<=')
->execute();
}
} catch (\Exception $e) {
$this->logger
->error('Unable to delete extra persistent tokens for user with uid @uid', [
'@uid' => $uid,
]);
}
}
return $token;
}
public function updateToken(PersistentToken $token) {
$originalInstance = $token
->getInstance();
$token = $token
->updateInstance($this->csrfToken
->get(Crypt::randomBytesBase64()));
try {
$this->connection
->update('persistent_login')
->fields([
'instance' => $token
->getInstance(),
'refreshed' => $token
->getRefreshed()
->getTimestamp(),
])
->condition('series', $token
->getSeries())
->condition('instance', $originalInstance)
->execute();
} catch (\Exception $e) {
throw new TokenException("An error occurred updating the token", 0, $e);
}
return $token;
}
public function deleteToken(PersistentToken $token) {
try {
$this->connection
->delete('persistent_login')
->condition('series', $token
->getSeries())
->condition('instance', $token
->getInstance())
->execute();
} catch (\Exception $e) {
throw new TokenException("An error occurred trying to delete the token", 0, $e);
}
return $token
->setInvalid();
}
public function cleanupExpiredTokens() {
try {
$this->connection
->delete('persistent_login')
->condition('expires', $this->time
->getRequestTime(), '<')
->execute();
} catch (\Exception $e) {
$this->logger
->error('An error occurred while removing expired tokens');
}
}
public function getTokensForUser(UserInterface $user) {
$tokens = [];
try {
$tokensResult = $this->connection
->select('persistent_login', 'pl')
->fields('pl', [
'uid',
'series',
'instance',
'created',
'refreshed',
'expires',
])
->condition('uid', $user
->id())
->condition('expires', $this->time
->getRequestTime(), '>')
->orderBy('created')
->execute();
while ($tokenArray = $tokensResult
->fetchAssoc()) {
$tokens[] = PersistentToken::createFromArray($tokenArray);
}
} catch (\Exception $e) {
$this->logger
->error('Unable to list tokens for user with uid @uid', [
'@uid' => $user
->id(),
]);
}
return $tokens;
}
}