<?php
declare(strict_types=1);
namespace SHServ\Integrations\GAuth\Store;
use GNexus\GAuth\Contract\TokenStoreInterface;
use GNexus\GAuth\DTO\TokenSet;
use Fury\Modules\ThinBuilder\ThinBuilder;
final class DbTokenStore implements TokenStoreInterface
{
private ThinBuilder $tb;
public function __construct(ThinBuilder $tb)
{
$this->tb = $tb;
}
public function put(string $key, TokenSet $tokenSet, ?int $userId = null): void
{
$expiresAt = $tokenSet->expiresAt;
$data = [
'session_token' => $key,
'access_token' => $tokenSet->accessToken,
'refresh_token' => $tokenSet->refreshToken,
'expires_at' => $expiresAt ? $expiresAt->format('Y-m-d H:i:s') : null,
'ip_address' => $this->getClientIp(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
'updated_at' => date('Y-m-d H:i:s'),
];
if ($userId !== null) {
$data['user_id'] = $userId;
}
$existing = $this->tb->select('shserv_sessions', ['id'], [['session_token', '=', $key]]);
if ($existing) {
$this->tb->update('shserv_sessions', $data, [['session_token', '=', $key]]);
} else {
$this->tb->insert('shserv_sessions', $data);
}
}
public function get(string $key): ?TokenSet
{
$result = $this->tb->select('shserv_sessions', ['access_token', 'refresh_token', 'expires_at'], [['session_token', '=', $key]]);
if (!$result) {
return null;
}
$row = $result[0];
$expiresAt = $row['expires_at'] ? new \DateTimeImmutable($row['expires_at']) : null;
return new TokenSet(
accessToken: (string) $row['access_token'],
refreshToken: isset($row['refresh_token']) ? (string) $row['refresh_token'] : null,
tokenType: 'Bearer',
expiresIn: $expiresAt ? (int) $expiresAt->format('U') - time() : 0,
expiresAt: $expiresAt,
);
}
public function forget(string $key): void
{
$this->tb->delete('shserv_sessions', [['session_token', '=', $key]]);
}
public function updateUserId(string $key, int $userId): void
{
$this->tb->update('shserv_sessions', [
'user_id' => $userId,
'updated_at' => date('Y-m-d H:i:s'),
], [['session_token', '=', $key]]);
}
private function getClientIp(): ?string
{
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[0]);
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
return $_SERVER['REMOTE_ADDR'] ?? null;
}
}