Redesignes and fixes the agents page

main
Yasen Pramatarov 2025-01-26 00:11:19 +02:00
parent 06cc20fb2a
commit df200aae64
6 changed files with 251 additions and 93 deletions

View File

@ -8,61 +8,163 @@
* to allow time-based invalidation if needed.
*/
// Get any new messages
include '../app/includes/messages.php';
include '../app/includes/messages-show.php';
// Constants for session keys and cache settings
define('SESSION_CACHE_SUFFIX', '_cache');
define('SESSION_CACHE_TIME_SUFFIX', '_cache_time');
define('CACHE_EXPIRY_TIME', 3600); // 1 hour in seconds
// Input validation
$action = isset($_GET['action']) ? htmlspecialchars(trim($_GET['action']), ENT_QUOTES, 'UTF-8') : '';
$agentId = filter_input(INPUT_GET, 'agent', FILTER_VALIDATE_INT);
$action = $_REQUEST['action'] ?? '';
$agent = $_REQUEST['agent'] ?? '';
require '../app/classes/agent.php';
require '../app/classes/host.php';
$agentObject = new Agent($dbWeb);
$hostObject = new Host($dbWeb);
// if it's a POST request, it's saving to cache
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// read the JSON sent from javascript
$data = file_get_contents("php://input");
$result = json_decode($data, true);
// store the data in the session
if ($result) {
$_SESSION["agent{$agent}_cache"] = $result;
$_SESSION["agent{$agent}_cache_time"] = time(); // store the cache time
echo json_encode([
'status' => 'success',
'message' => "Cache for agent {$agent} is stored."
]);
} elseif ($result === null && !empty($agent)) {
unset($_SESSION["agent{$agent}_cache"]);
unset($_SESSION["agent{$agent}_cache_time"]);
echo json_encode([
'status' => 'success',
'message' => "Cache for agent {$agent} is cleared."
]);
} else {
echo json_encode([
'status' => 'error',
'message' => 'Invalid data'
]);
}
//// if it's a GET request, it's read/load from cache
//} elseif ($loadcache === true) {
//
// // check if cached data exists in session
// if (isset($_SESSION["agent{$agent}_cache"])) {
// // return the cached data in JSON format
// echo json_encode(['status' => 'success', 'data' => $_SESSION["agent{$agent}_cache"]]);
// } else {
// // if no cached data exists
// echo json_encode(['status' => 'error', 'message' => 'No cached data found']);
// }
// no form submitted, show the templates
} else {
$agentDetails = $agentObject->getAgentDetails($platform_id);
include '../app/templates/agent-list.php';
/**
* Get the cache key for an agent
* @param int $agentId The agent ID
* @param string $suffix The suffix to append (_cache or _cache_time)
* @return string The cache key
*/
function getAgentCacheKey($agentId, $suffix) {
return "agent{$agentId}{$suffix}";
}
?>
/**
* Check if cache is expired
* @param int $agentId The agent ID
* @return bool True if cache is expired or doesn't exist
*/
function isCacheExpired($agentId) {
$timeKey = getAgentCacheKey($agentId, SESSION_CACHE_TIME_SUFFIX);
if (!isset($_SESSION[$timeKey])) {
return true;
}
return (time() - $_SESSION[$timeKey]) > CACHE_EXPIRY_TIME;
}
// Handle POST request (saving to cache)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validate agent ID for POST operations
if ($agentId === false || $agentId === null) {
Messages::flash('ERROR', 'DEFAULT', 'Invalid agent ID format');
echo json_encode(['status' => 'error', 'message' => 'Invalid agent ID format']);
exit;
}
// Read and validate JSON data
$jsonData = file_get_contents("php://input");
if ($jsonData === false) {
Messages::flash('ERROR', 'DEFAULT', 'Failed to read input data');
echo json_encode(['status' => 'error', 'message' => 'Failed to read input data']);
exit;
}
$data = json_decode($jsonData, true);
// Handle cache clearing
if ($data === null && !empty($agentId)) {
$cacheKey = getAgentCacheKey($agentId, SESSION_CACHE_SUFFIX);
$timeKey = getAgentCacheKey($agentId, SESSION_CACHE_TIME_SUFFIX);
unset($_SESSION[$cacheKey]);
unset($_SESSION[$timeKey]);
Messages::flash('SUCCESS', 'DEFAULT', "Cache for agent {$agentId} is cleared.");
echo json_encode([
'status' => 'success',
'message' => "Cache for agent {$agentId} is cleared."
]);
}
// Handle cache storing
elseif ($data) {
$cacheKey = getAgentCacheKey($agentId, SESSION_CACHE_SUFFIX);
$timeKey = getAgentCacheKey($agentId, SESSION_CACHE_TIME_SUFFIX);
$_SESSION[$cacheKey] = $data;
$_SESSION[$timeKey] = time();
Messages::flash('SUCCESS', 'DEFAULT', "Cache for agent {$agentId} is stored.");
echo json_encode([
'status' => 'success',
'message' => "Cache for agent {$agentId} is stored."
]);
}
else {
Messages::flash('ERROR', 'DEFAULT', 'Invalid data format');
echo json_encode(['status' => 'error', 'message' => 'Invalid data format']);
}
// Handle AJAX requests
} elseif (isset($_GET['action'])) {
$action = $_GET['action'];
$agentId = filter_input(INPUT_GET, 'agent', FILTER_VALIDATE_INT);
if ($action === 'fetch') {
$response = ['status' => 'success', 'data' => $data];
echo json_encode($response);
exit;
}
if ($action === 'status') {
$response = ['status' => 'success', 'data' => $statusData];
echo json_encode($response);
exit;
}
// Handle template display
} else {
// Validate platform_id is set
if (!isset($platform_id)) {
Messages::flash('ERROR', 'DEFAULT', 'Platform ID is not set');
}
// Get host details for this platform
$hostDetails = $hostObject->getHostDetails($platform_id);
// Group agents by host
$agentsByHost = [];
foreach ($hostDetails as $host) {
$hostId = $host['id'];
$agentsByHost[$hostId] = [
'host_name' => $host['name'],
'agents' => []
];
// Get agents for this host
$hostAgents = $agentObject->getAgentDetails($hostId);
if ($hostAgents) {
$agentsByHost[$hostId]['agents'] = $hostAgents;
}
// Generate JWT tokens for each agent beforehand
$agentTokens = [];
foreach ($agentsByHost[$hostId]['agents'] as $agent) {
$payload = [
'iss' => 'Jilo Web',
'aud' => $config['domain'],
'iat' => time(),
'exp' => time() + 3600,
'agent_id' => $agent['id']
];
$agentTokens[$agent['id']] = $agentObject->generateAgentToken($payload, $agent['secret_key']);
}
/**
* Now we have:
* $hostDetails - hosts in this platform
* $agentsByHost[$hostId]['agents'] - agents details by hostId
* $agentTokens[$agent['id']] - tokens for the agentsIds
*/
}
// Get any new messages
include '../app/includes/messages.php';
include '../app/includes/messages-show.php';
// Load the template
include '../app/templates/agents.php';
}

View File

@ -1,39 +0,0 @@
<!-- jilo agents -->
<div class="card text-center w-75 mx-lef">
<p class="h4 card-header">Jilo Agents on platform <?= htmlspecialchars($platform_id) ?> (<?= htmlspecialchars($platformDetails[0]['name']) ?>)</p>
<div class="card-body">
<?php foreach ($agentDetails as $agent) { ?>
<p class="card-text text-left" style="text-align: left;">
agent id: <strong><?= htmlspecialchars($agent['id']) ?></strong>
agent type: <?= htmlspecialchars($agent['agent_type_id']) ?> (<strong><?= htmlspecialchars($agent['agent_description']) ?></strong>)
<br />
endpoint: <strong><?= htmlspecialchars($agent['url']) ?><?= htmlspecialchars($agent['agent_endpoint']) ?></strong>
<br />
<?php
$payload = [
'iss' => 'Jilo Web',
'aud' => $config['domain'],
'iat' => time(),
'exp' => time() + 3600,
'agent_id' => $agent['id']
];
$jwt = $agentObject->generateAgentToken($payload, $agent['secret_key']);
// print_r($_SESSION);
?>
<?php if (isset($_SESSION["agent{$agent['id']}_cache"])) { ?>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-status" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get the agent status" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '/status', '<?= htmlspecialchars($jwt) ?>', true)">get status</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-fetch" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get data from the agent" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '<?= htmlspecialchars($agent['agent_endpoint']) ?>', '<?= htmlspecialchars($jwt) ?>', true)">fetch data</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-cache" class="btn btn-secondary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="load cache" onclick="loadCache('<?= htmlspecialchars($agent['id']) ?>')">load cache</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-clear" class="btn btn-danger" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="clear cache" onclick="clearCache('<?= htmlspecialchars($agent['id']) ?>')">clear cache</button>
<span id="cacheInfo<?= htmlspecialchars($agent['id']) ?>" style="margin: 5px 0;"></span>
<?php } else { ?>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-status" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get the agent status" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '/status', '<?= htmlspecialchars($jwt) ?>', true)">get status</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-fetch" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get data from the agent" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '<?= htmlspecialchars($agent['agent_endpoint']) ?>', '<?= htmlspecialchars($jwt) ?>')">fetch data</button>
<button style="display: none" disabled id="agent<?= htmlspecialchars($agent['id']) ?>-cache" class="btn btn-secondary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="load cache" onclick="loadCache('<?= htmlspecialchars($agent['id']) ?>')">load cache</button>
<button style="display: none" disabled id="agent<?= htmlspecialchars($agent['id']) ?>-clear" class="btn btn-danger" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="clear cache" onclick="clearCache('<?= htmlspecialchars($agent['id']) ?>')">clear cache</button>
<span style="display: none" id="cacheInfo<?= htmlspecialchars($agent['id']) ?>" style="margin: 5px 0;"></span>
<?php } ?>
</p>
<pre class="results" id="result<?= htmlspecialchars($agent['id']) ?>">click a button to display data from the agent.</pre>
<?php } ?>

View File

@ -0,0 +1,94 @@
<!-- agents live data -->
<div class="container-fluid mt-2">
<div class="row mb-4">
<div class="col-12 mb-4">
<h2 class="mb-0">Jilo Agents on platform <?= htmlspecialchars($platform_id) ?> (<?= htmlspecialchars($platformDetails[0]['name']) ?>)</h2>
<small>Manage and monitor agents on this platform.</small>
</div>
</div>
<!-- hosts and their agents -->
<div class="row">
<?php foreach ($agentsByHost as $hostId => $hostData): ?>
<div class="col-12 mb-4">
<div class="card">
<div class="card-header bg-light">
<h5 class="mb-0">
<i class="fas fa-network-wired me-2 text-secondary"></i>
Host: <?= htmlspecialchars($hostData['host_name']) ?>
<a href="<?= htmlspecialchars($app_root) ?>?page=settings#platform-<?= htmlspecialchars($platform_id) ?>host-<?= htmlspecialchars($hostId) ?>" class="text-decoration-none">
<i class="fas fa-edit ms-2"></i>
</a>
</h5>
</div>
<div class="card-body">
<?php if (empty($hostData['agents'])): ?>
<p class="text-muted">No agents on this host.</p>
<?php else: ?>
<?php foreach ($hostData['agents'] as $agent): ?>
<div class="agent-item mb-4 pb-3 border-bottom">
<div class="d-flex align-items-center mb-2">
<div class="flex-grow-1">
<i class="fas fa-robot me-2 text-secondary"></i>
<strong>Agent ID:</strong> <?= htmlspecialchars($agent['id']) ?> |
<strong>Type:</strong> <?= htmlspecialchars($agent['agent_type_id']) ?> (<?= htmlspecialchars($agent['agent_description']) ?>) |
<strong>Endpoint:</strong> <?= htmlspecialchars($agent['url']) ?><?= htmlspecialchars($agent['agent_endpoint']) ?>
<a href="<?= htmlspecialchars($app_root) ?>?page=settings#platform-<?= htmlspecialchars($platform_id) ?>agent-<?= htmlspecialchars($agent['id']) ?>" class="text-decoration-none">
<i class="fas fa-edit ms-2"></i>
</a>
</div>
</div>
<div class="btn-group" role="group">
<button id="agent<?= htmlspecialchars($agent['id']) ?>-status"
class="btn btn-primary"
data-toggle="tooltip"
data-trigger="hover"
data-placement="bottom"
title="Get the agent status"
onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '/status', '<?= htmlspecialchars($agentTokens[$agent['id']]) ?>', true)">
Get Status
</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-fetch"
class="btn btn-primary"
data-toggle="tooltip"
data-trigger="hover"
data-placement="bottom"
title="Get data from the agent"
onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '<?= htmlspecialchars($agent['agent_endpoint']) ?>', '<?= htmlspecialchars($agentTokens[$agent['id']]) ?>', <?= isset($_SESSION["agent{$agent['id']}_cache"]) ? 'true' : 'false' ?>)">
Fetch Data
</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-cache"
<?= !isset($_SESSION["agent{$agent['id']}_cache"]) ? 'style="display:none;" ' : '' ?>
class="btn btn-secondary"
data-toggle="tooltip"
data-trigger="hover"
data-placement="bottom"
title="Load cache"
onclick="loadCache('<?= htmlspecialchars($agent['id']) ?>')">
Load Cache
</button>
<button id="agent<?= htmlspecialchars($agent['id']) ?>-clear"
<?= !isset($_SESSION["agent{$agent['id']}_cache"]) ? 'style="display:none;" ' : '' ?>
class="btn btn-danger"
data-toggle="tooltip"
data-trigger="hover"
data-placement="bottom"
title="Clear cache"
onclick="clearCache('<?= htmlspecialchars($agent['id']) ?>')">
Clear Cache
</button>
</div>
<span id="cacheInfo<?= htmlspecialchars($agent['id']) ?>" class="ms-2 <?= isset($_SESSION["agent{$agent['id']}_cache"]) ? '' : 'd-none' ?>"></span>
<pre class="results mt-3" id="result<?= htmlspecialchars($agent['id']) ?>">Click a button to display data from the agent.</pre>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- agents live data -->

View File

@ -61,7 +61,7 @@ $timeNow = new DateTime('now', new DateTimeZone($userTimezone));
</a>
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=agents">
<li class="list-group-item<?php if ($page === 'agents') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
<i class="fas fa-mask" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="jilo agents"></i>jilo agents
<i class="fas fa-robot" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="jilo agents"></i>jilo agents
</li>
</a>

View File

@ -2,6 +2,7 @@
<!-- jilo agent status -->
<div class="d-flex align-items-center flex-wrap border-top p-3">
<div class="d-flex align-items-center me-4">
<i class="fas fa-robot me-2 text-secondary"></i>
<span class="me-2">Jilo agent
<a href="<?= htmlspecialchars($app_root) ?>?page=settings#platform-<?= htmlspecialchars($platform['id']) ?>agent-<?= htmlspecialchars($agent['id']) ?>" class="text-decoration-none">
<?= htmlspecialchars($agent['agent_description']) ?>

View File

@ -206,7 +206,7 @@ function saveResultToSession(result, agent_id) {
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log("Data saved to session successfully.");
//DEBUG console.log("Data saved to session successfully.");
}
};