add SessionTimeout logic

This commit is contained in:
root
2026-03-10 16:45:08 -04:00
parent 2e9a391280
commit 311bb93977
15 changed files with 534 additions and 292 deletions
@@ -0,0 +1,39 @@
<?php
namespace App\Services\Auth;
use Illuminate\Session\Store;
class SessionActivityService
{
public function __construct(private Store $session)
{
}
public function hasLastActivity(): bool
{
return $this->session->has('last_activity');
}
public function getLastActivity(): ?int
{
$value = $this->session->get('last_activity');
return $value !== null ? (int) $value : null;
}
public function setLastActivity(int $timestamp): void
{
$this->session->put('last_activity', $timestamp);
}
public function clearLastActivity(): void
{
$this->session->forget('last_activity');
}
public function invalidate(): void
{
$this->session->invalidate();
$this->session->regenerateToken();
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Services\Auth;
use App\Config\SessionTimeout;
use Illuminate\Support\Facades\URL;
class SessionTimeoutConfigService
{
public function config(): array
{
return [
'timeout' => SessionTimeout::TIMEOUT_DURATION,
'warning_time' => SessionTimeout::WARNING_THRESHOLD,
'check_interval' => SessionTimeout::CHECK_INTERVAL,
'logout_url' => URL::to('/auth/logout'),
'keep_alive_url' => route('session.timeout.ping'),
'check_url' => route('session.timeout.check'),
];
}
}
@@ -0,0 +1,72 @@
<?php
namespace App\Services\Auth;
use App\Config\SessionTimeout;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;
class SessionTimeoutService
{
public function __construct(
private SessionActivityService $activityService
) {
}
public function checkTimeout(): array
{
if (!$this->activityService->hasLastActivity()) {
return $this->expireSession();
}
$lastActivity = (int) $this->activityService->getLastActivity();
$elapsed = time() - $lastActivity;
if ($elapsed > SessionTimeout::TIMEOUT_DURATION) {
return $this->expireSession();
}
if ($elapsed > SessionTimeout::WARNING_THRESHOLD) {
return [
'status' => 'warning',
'time_remaining' => SessionTimeout::TIMEOUT_DURATION - $elapsed,
];
}
return [
'status' => 'active',
'time_remaining' => SessionTimeout::TIMEOUT_DURATION - $elapsed,
];
}
public function pingActivity(): array
{
if (
!$this->activityService->hasLastActivity()
|| (time() - (int) $this->activityService->getLastActivity() > SessionTimeout::TIMEOUT_DURATION)
) {
return $this->expireSession();
}
$this->activityService->setLastActivity(time());
return [
'status' => 'active',
'time_remaining' => SessionTimeout::TIMEOUT_DURATION,
];
}
private function expireSession(): array
{
Log::info('Session expired due to inactivity.');
$this->activityService->clearLastActivity();
$this->activityService->invalidate();
return [
'status' => 'expired',
'redirect' => URL::to('/login'),
'message' => 'Your session has expired due to inactivity.',
'time_remaining' => 0,
];
}
}