diff --git a/api/.env b/api/.env index 9e7c528..4a7e56e 100644 --- a/api/.env +++ b/api/.env @@ -6,4 +6,4 @@ LXD_CLIENT_CERT=/etc/ssl/lxdapp/client.crt LXD_CLIENT_KEY=/etc/ssl/lxdapp/client.key LXD_IMAGE_FINGERPRINT=2edfd84b1396 AUTH_KEY=R9kX2HFA7ZjLdVYm8TsQWpCeNuB1v0GrS6MI4axf - +STATEDIR=/var/www/html/lxd-app/api/public/last-access-logs \ No newline at end of file diff --git a/api/public/index.php b/api/public/index.php index 9fef4d0..9a1ee57 100644 --- a/api/public/index.php +++ b/api/public/index.php @@ -14,6 +14,7 @@ use App\Controllers\HandoffController; use App\Services\LxdService; use Zounar\PHPProxy\Proxy; use App\Utils\LogWriterHelper; +use App\Utils\ContainerHelper; require __DIR__ . '/../vendor/autoload.php'; diff --git a/api/src/Controllers/HandoffController.php b/api/src/Controllers/HandoffController.php index 744f69a..e45b8e3 100644 --- a/api/src/Controllers/HandoffController.php +++ b/api/src/Controllers/HandoffController.php @@ -5,6 +5,7 @@ namespace App\Controllers; use App\Services\LxdService; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use App\Utils\ContainerHelper; class HandoffController { @@ -13,9 +14,9 @@ class HandoffController // if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); } $q = $req->getQueryParams(); - $name = (string)($q['name'] ?? ''); + $name = ContainerHelper::getName($req); $id = (string)($q['handoff'] ?? ''); - $path = (string)($q['path'] ?? '/login'); + $path = (string)($q['path'] ?? '/'); if (!$name || !$id) { return $this->html($res, 400, '

Bad request

'); diff --git a/api/src/Controllers/LoginController.php b/api/src/Controllers/LoginController.php index 075b82c..49406ac 100644 --- a/api/src/Controllers/LoginController.php +++ b/api/src/Controllers/LoginController.php @@ -7,6 +7,7 @@ use App\Services\LxdService; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use App\Utils\LogWriterHelper; +use App\Utils\ContainerHelper; class LoginController { @@ -16,12 +17,7 @@ class LoginController public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { try { - $origin = $request->getHeaderLine('Origin'); - $domain = !empty($origin) ? parse_url($origin, PHP_URL_HOST) : $request->getHeaderLine('Host'); - - $configPath = __DIR__ . '/../../config.json'; - $config = file_exists($configPath) ? json_decode(file_get_contents($configPath), true) : []; - $name = $config[$domain] ?? null; + $name = ContainerHelper::getName($request); $params = (array)$request->getParsedBody(); @@ -42,10 +38,8 @@ class LoginController if ($status !== 'Running') { $lxd->startContainer($name); } - - // Log path only (avoid leaking query in logs) - $uri = $request->getUri(); - LogWriterHelper::write($name, $uri->getPath()); + + LogWriterHelper::write($name); // ---- NEW: create one-time handoff and store creds server-side ---- $handoffId = bin2hex(random_bytes(16)); @@ -56,12 +50,11 @@ class LoginController ]; // sanitize the container path (not a full URL!) - $path = $this->sanitizeRedirectPath($params['redirect'] ?? '/login'); + // $path = $this->sanitizeRedirectPath($params['redirect'] ?? '/login'); // Client goes to waiting page; when ready it will be sent to the bridge - $redirect = '/waiting?name=' . rawurlencode($name) - . '&handoff=' . rawurlencode($handoffId) - . '&path=' . rawurlencode($path); + $redirect = '/waiting?handoff=' . rawurlencode($handoffId); + //. '&path=' . rawurlencode($path); return $this->json($response, [ 'status' => 'success', @@ -78,8 +71,7 @@ class LoginController public function status(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { - $queryParams = $request->getQueryParams(); - $name = $queryParams['name'] ?? ''; + $name = ContainerHelper::getName($request); if (empty($name)) { return $this->json($response, [ @@ -115,6 +107,7 @@ class LoginController return $this->json($response, [ 'status' => 'ready', 'ip' => $ip, + 'name' => $name, 'message' => 'Container is ready', ]); } @@ -167,4 +160,5 @@ class LoginController return in_array($path, $allow, true) ? $path : '/login'; } } + \ No newline at end of file diff --git a/api/src/Scripts/auto-stop-containers.php b/api/src/Scripts/auto-stop-containers.php index 6294602..5d3d893 100755 --- a/api/src/Scripts/auto-stop-containers.php +++ b/api/src/Scripts/auto-stop-containers.php @@ -8,7 +8,7 @@ use App\Services\LxdService; $lxdService = new LxdService(); // Define the directory containing access logs -$logDir = realpath(__DIR__ . '/../../public/last-access-logs'); // Adjust if you're in /app/src/Cron or similar +$logDir = $_ENV['STATEDIR'] ?? "/var/www/html/lxd-app/api/public/last-access-logs"; // Define the idle threshold in minutes $thresholdMinutes = 30; @@ -18,23 +18,15 @@ foreach (glob($logDir . '/*.txt') as $filePath) { // Extract the container name from the file name $containerName = basename($filePath, '.txt'); - // Get the last line from the log file - $lastLine = getLastLine($filePath); - if (!$lastLine) { - echo "No access logs found for $containerName.\n"; + // Get the last modified time of the file + $lastModified = filemtime($filePath); + if (!$lastModified) { + echo "Failed to get modification time for $containerName.\n"; continue; } - // Parse the timestamp from the last log entry - $parts = explode(' : ', $lastLine); - if (!isset($parts[0])) continue; - - $lastAccess = DateTime::createFromFormat('Y-m-d H:i:s', trim($parts[0])); - if (!$lastAccess) continue; - - // Calculate the idle time in seconds - $now = new DateTime(); - $interval = $now->getTimestamp() - $lastAccess->getTimestamp(); + $now = time(); + $interval = $now - $lastModified; // Check if the container has been idle for longer than the threshold if ($interval > $thresholdMinutes * 60) { @@ -49,20 +41,7 @@ foreach (glob($logDir . '/*.txt') as $filePath) { echo "Container $containerName does not exist.\n"; } } catch (Throwable $e) { - // Handle any errors that occur while stopping the container echo "Error stopping $containerName: " . $e->getMessage() . "\n"; } } } - -/** - * Get the last non-empty line from a file. - * - * @param string $filePath Path to the file. - * @return string|null The last line, or null if the file is empty. - */ -function getLastLine(string $filePath): ?string -{ - $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - return $lines ? end($lines) : null; -} diff --git a/api/src/Utils/ContainerHelper.php b/api/src/Utils/ContainerHelper.php new file mode 100644 index 0000000..ceca7ed --- /dev/null +++ b/api/src/Utils/ContainerHelper.php @@ -0,0 +1,33 @@ +getHeaderLine('Origin'); + $domain = !empty($origin) ? parse_url($origin, PHP_URL_HOST) : $request->getHeaderLine('Host'); + + // Load config.json once + $config = self::getConfig(); + return $config[$domain] ?? null; + } + + protected static function getConfig(): array + { + static $config = null; + + if ($config !== null) { + return $config; + } + + $configPath = __DIR__ . '/../../config.json'; + + return file_exists($configPath) ? json_decode(file_get_contents($configPath), true) : []; + } +} diff --git a/api/src/Utils/LogWriterHelper.php b/api/src/Utils/LogWriterHelper.php index 74d461f..4c897ff 100644 --- a/api/src/Utils/LogWriterHelper.php +++ b/api/src/Utils/LogWriterHelper.php @@ -3,19 +3,7 @@ namespace App\Utils; class LogWriterHelper { - public static function write(string $name, string $uri): void { - // Dynamically resolve the log directory relative to the current file - $logDir = realpath(__DIR__ . '/../../public/last-access-logs'); - - // If the resolved path doesn't exist (e.g., public dir was missing), create it - if (!$logDir) { - $logDir = __DIR__ . '/../../public/last-access-logs'; - if (!file_exists($logDir)) { - mkdir($logDir, 0777, true); - } - } - - $logLine = date("Y-m-d H:i:s") . " : " . $uri . "\n"; - file_put_contents($logDir . '/' . $name . '.txt', $logLine, FILE_APPEND); + public static function write(string $name): void { + touch($_ENV['STATEDIR']."/".$name); } } \ No newline at end of file diff --git a/index.php b/index.php index 47733c3..15fed4c 100644 --- a/index.php +++ b/index.php @@ -27,7 +27,7 @@ $container = $config[$host] ?? null; $lxd = new LxdService(); // === Helper URLs === -$redirectBase = parseUrl("$host/app?auth=ok&redirect=" . urlencode(getFullUrl())); +$redirectBase = parseUrl("$host/app"); $waitingPage = parseUrl("$host/app/waiting?name=$container&redirect=" . urlencode(getFullUrl())); // === If container is missing or invalid === if (!$container || !$lxd->containerExists($container)) { @@ -71,7 +71,8 @@ function proxy(string $name, string $targetUrl): void { $_SERVER['HTTP_PROXY_TARGET_URL'] = $targetUrl; $responseCode = Proxy::run(); - writeLog($name, $targetUrl); + touch($_ENV['STATEDIR']."/".$name); + } function getFullUrl(): string {