fix: update code
This commit is contained in:
2
api/.env
2
api/.env
@ -6,4 +6,4 @@ LXD_CLIENT_CERT=/etc/ssl/lxdapp/client.crt
|
|||||||
LXD_CLIENT_KEY=/etc/ssl/lxdapp/client.key
|
LXD_CLIENT_KEY=/etc/ssl/lxdapp/client.key
|
||||||
LXD_IMAGE_FINGERPRINT=2edfd84b1396
|
LXD_IMAGE_FINGERPRINT=2edfd84b1396
|
||||||
AUTH_KEY=R9kX2HFA7ZjLdVYm8TsQWpCeNuB1v0GrS6MI4axf
|
AUTH_KEY=R9kX2HFA7ZjLdVYm8TsQWpCeNuB1v0GrS6MI4axf
|
||||||
|
STATEDIR=/var/www/html/lxd-app/api/public/last-access-logs
|
||||||
@ -14,6 +14,7 @@ use App\Controllers\HandoffController;
|
|||||||
use App\Services\LxdService;
|
use App\Services\LxdService;
|
||||||
use Zounar\PHPProxy\Proxy;
|
use Zounar\PHPProxy\Proxy;
|
||||||
use App\Utils\LogWriterHelper;
|
use App\Utils\LogWriterHelper;
|
||||||
|
use App\Utils\ContainerHelper;
|
||||||
|
|
||||||
require __DIR__ . '/../vendor/autoload.php';
|
require __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ namespace App\Controllers;
|
|||||||
use App\Services\LxdService;
|
use App\Services\LxdService;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use App\Utils\ContainerHelper;
|
||||||
|
|
||||||
class HandoffController
|
class HandoffController
|
||||||
{
|
{
|
||||||
@ -13,9 +14,9 @@ class HandoffController
|
|||||||
// if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); }
|
// if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); }
|
||||||
|
|
||||||
$q = $req->getQueryParams();
|
$q = $req->getQueryParams();
|
||||||
$name = (string)($q['name'] ?? '');
|
$name = ContainerHelper::getName($req);
|
||||||
$id = (string)($q['handoff'] ?? '');
|
$id = (string)($q['handoff'] ?? '');
|
||||||
$path = (string)($q['path'] ?? '/login');
|
$path = (string)($q['path'] ?? '/');
|
||||||
|
|
||||||
if (!$name || !$id) {
|
if (!$name || !$id) {
|
||||||
return $this->html($res, 400, '<h1>Bad request</h1>');
|
return $this->html($res, 400, '<h1>Bad request</h1>');
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use App\Services\LxdService;
|
|||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use App\Utils\LogWriterHelper;
|
use App\Utils\LogWriterHelper;
|
||||||
|
use App\Utils\ContainerHelper;
|
||||||
|
|
||||||
class LoginController
|
class LoginController
|
||||||
{
|
{
|
||||||
@ -16,12 +17,7 @@ class LoginController
|
|||||||
public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$origin = $request->getHeaderLine('Origin');
|
$name = ContainerHelper::getName($request);
|
||||||
$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;
|
|
||||||
|
|
||||||
$params = (array)$request->getParsedBody();
|
$params = (array)$request->getParsedBody();
|
||||||
|
|
||||||
@ -43,9 +39,7 @@ class LoginController
|
|||||||
$lxd->startContainer($name);
|
$lxd->startContainer($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log path only (avoid leaking query in logs)
|
LogWriterHelper::write($name);
|
||||||
$uri = $request->getUri();
|
|
||||||
LogWriterHelper::write($name, $uri->getPath());
|
|
||||||
|
|
||||||
// ---- NEW: create one-time handoff and store creds server-side ----
|
// ---- NEW: create one-time handoff and store creds server-side ----
|
||||||
$handoffId = bin2hex(random_bytes(16));
|
$handoffId = bin2hex(random_bytes(16));
|
||||||
@ -56,12 +50,11 @@ class LoginController
|
|||||||
];
|
];
|
||||||
|
|
||||||
// sanitize the container path (not a full URL!)
|
// 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
|
// Client goes to waiting page; when ready it will be sent to the bridge
|
||||||
$redirect = '/waiting?name=' . rawurlencode($name)
|
$redirect = '/waiting?handoff=' . rawurlencode($handoffId);
|
||||||
. '&handoff=' . rawurlencode($handoffId)
|
//. '&path=' . rawurlencode($path);
|
||||||
. '&path=' . rawurlencode($path);
|
|
||||||
|
|
||||||
return $this->json($response, [
|
return $this->json($response, [
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
@ -78,8 +71,7 @@ class LoginController
|
|||||||
|
|
||||||
public function status(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
public function status(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||||
{
|
{
|
||||||
$queryParams = $request->getQueryParams();
|
$name = ContainerHelper::getName($request);
|
||||||
$name = $queryParams['name'] ?? '';
|
|
||||||
|
|
||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
return $this->json($response, [
|
return $this->json($response, [
|
||||||
@ -115,6 +107,7 @@ class LoginController
|
|||||||
return $this->json($response, [
|
return $this->json($response, [
|
||||||
'status' => 'ready',
|
'status' => 'ready',
|
||||||
'ip' => $ip,
|
'ip' => $ip,
|
||||||
|
'name' => $name,
|
||||||
'message' => 'Container is ready',
|
'message' => 'Container is ready',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -168,3 +161,4 @@ class LoginController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ use App\Services\LxdService;
|
|||||||
$lxdService = new LxdService();
|
$lxdService = new LxdService();
|
||||||
|
|
||||||
// Define the directory containing access logs
|
// 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
|
// Define the idle threshold in minutes
|
||||||
$thresholdMinutes = 30;
|
$thresholdMinutes = 30;
|
||||||
@ -18,23 +18,15 @@ foreach (glob($logDir . '/*.txt') as $filePath) {
|
|||||||
// Extract the container name from the file name
|
// Extract the container name from the file name
|
||||||
$containerName = basename($filePath, '.txt');
|
$containerName = basename($filePath, '.txt');
|
||||||
|
|
||||||
// Get the last line from the log file
|
// Get the last modified time of the file
|
||||||
$lastLine = getLastLine($filePath);
|
$lastModified = filemtime($filePath);
|
||||||
if (!$lastLine) {
|
if (!$lastModified) {
|
||||||
echo "No access logs found for $containerName.\n";
|
echo "Failed to get modification time for $containerName.\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the timestamp from the last log entry
|
$now = time();
|
||||||
$parts = explode(' : ', $lastLine);
|
$interval = $now - $lastModified;
|
||||||
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();
|
|
||||||
|
|
||||||
// Check if the container has been idle for longer than the threshold
|
// Check if the container has been idle for longer than the threshold
|
||||||
if ($interval > $thresholdMinutes * 60) {
|
if ($interval > $thresholdMinutes * 60) {
|
||||||
@ -49,20 +41,7 @@ foreach (glob($logDir . '/*.txt') as $filePath) {
|
|||||||
echo "Container $containerName does not exist.\n";
|
echo "Container $containerName does not exist.\n";
|
||||||
}
|
}
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
// Handle any errors that occur while stopping the container
|
|
||||||
echo "Error stopping $containerName: " . $e->getMessage() . "\n";
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
33
api/src/Utils/ContainerHelper.php
Normal file
33
api/src/Utils/ContainerHelper.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Utils;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class ContainerHelper
|
||||||
|
{
|
||||||
|
public static function getName(ServerRequestInterface $request): ?string
|
||||||
|
{
|
||||||
|
// Try to get Origin header, fallback to Host
|
||||||
|
$origin = $request->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) : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,19 +3,7 @@
|
|||||||
namespace App\Utils;
|
namespace App\Utils;
|
||||||
|
|
||||||
class LogWriterHelper {
|
class LogWriterHelper {
|
||||||
public static function write(string $name, string $uri): void {
|
public static function write(string $name): void {
|
||||||
// Dynamically resolve the log directory relative to the current file
|
touch($_ENV['STATEDIR']."/".$name);
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ $container = $config[$host] ?? null;
|
|||||||
$lxd = new LxdService();
|
$lxd = new LxdService();
|
||||||
|
|
||||||
// === Helper URLs ===
|
// === 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()));
|
$waitingPage = parseUrl("$host/app/waiting?name=$container&redirect=" . urlencode(getFullUrl()));
|
||||||
// === If container is missing or invalid ===
|
// === If container is missing or invalid ===
|
||||||
if (!$container || !$lxd->containerExists($container)) {
|
if (!$container || !$lxd->containerExists($container)) {
|
||||||
@ -71,7 +71,8 @@ function proxy(string $name, string $targetUrl): void {
|
|||||||
$_SERVER['HTTP_PROXY_TARGET_URL'] = $targetUrl;
|
$_SERVER['HTTP_PROXY_TARGET_URL'] = $targetUrl;
|
||||||
|
|
||||||
$responseCode = Proxy::run();
|
$responseCode = Proxy::run();
|
||||||
writeLog($name, $targetUrl);
|
touch($_ENV['STATEDIR']."/".$name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFullUrl(): string {
|
function getFullUrl(): string {
|
||||||
|
|||||||
Reference in New Issue
Block a user