Compare commits

...

16 Commits
v0.2.1 ... main

22 changed files with 328 additions and 31 deletions

View File

@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
--- ---
## Unreleased
#### Links
- upstream: https://code.lindeas.com/lindeas/jilo-web/compare/v0.2.1...HEAD
- codeberg: https://codeberg.org/lindeas/jilo-web/compare/v0.2.1...HEAD
- github: https://github.com/lindeas/jilo-web/compare/v0.2.1...HEAD
- gitlab: https://gitlab.com/lindeas/jilo-web/-/compare/v0.2.1...HEAD
### Added
- Added Jilo Server check and notice on error
- Added status page
---
## 0.2.1 - 2024-10-17 ## 0.2.1 - 2024-10-17
#### Links #### Links

View File

@ -43,6 +43,7 @@ Chart.js is used in this project and is licensed under the MIT License. See lice
- web server (deb: apache | nginx) - web server (deb: apache | nginx)
- php support in the web server (deb: php-fpm | libapache2-mod-php) - php support in the web server (deb: php-fpm | libapache2-mod-php)
- pdo and pdo_sqlite support in php (deb: php-db, php-sqlite3) uncomment in php.ini: ;extension=pdo_sqlite - pdo and pdo_sqlite support in php (deb: php-db, php-sqlite3) uncomment in php.ini: ;extension=pdo_sqlite
- php-curl module
## installation ## installation

View File

@ -15,6 +15,7 @@ class Agent {
ja.agent_type_id, ja.agent_type_id,
ja.url, ja.url,
ja.secret_key, ja.secret_key,
ja.check_period,
jat.description AS agent_description, jat.description AS agent_description,
jat.endpoint AS agent_endpoint jat.endpoint AS agent_endpoint
FROM FROM
@ -40,6 +41,31 @@ class Agent {
return $query->fetchAll(PDO::FETCH_ASSOC); return $query->fetchAll(PDO::FETCH_ASSOC);
} }
// get details of a specified agent ID
public function getAgentIDDetails($agent_id) {
$sql = 'SELECT
ja.id,
ja.platform_id,
ja.agent_type_id,
ja.url,
ja.secret_key,
ja.check_period,
jat.description AS agent_description,
jat.endpoint AS agent_endpoint
FROM
jilo_agents ja
JOIN
jilo_agent_types jat ON ja.agent_type_id = jat.id
WHERE
ja.id = :agent_id';
$query = $this->db->prepare($sql);
$query->bindParam(':agent_id', $agent_id);
$query->execute();
return $query->fetchAll(PDO::FETCH_ASSOC);
}
// get agent types // get agent types
public function getAgentTypes() { public function getAgentTypes() {
$sql = 'SELECT * $sql = 'SELECT *
@ -51,13 +77,29 @@ class Agent {
return $query->fetchAll(PDO::FETCH_ASSOC); return $query->fetchAll(PDO::FETCH_ASSOC);
} }
// get agent types already configured for a platform
public function getPlatformAgentTypes($platform_id) {
$sql = 'SELECT
id,
agent_type_id
FROM
jilo_agents
WHERE
platform_id = :platform_id';
$query = $this->db->prepare($sql);
$query->bindParam(':platform_id', $platform_id);
$query->execute();
return $query->fetchAll(PDO::FETCH_ASSOC);
}
// add new agent // add new agent
public function addAgent($platform_id, $newAgent) { public function addAgent($platform_id, $newAgent) {
try { try {
$sql = 'INSERT INTO jilo_agents $sql = 'INSERT INTO jilo_agents
(platform_id, agent_type_id, url, secret_key) (platform_id, agent_type_id, url, secret_key, check_period)
VALUES VALUES
(:platform_id, :agent_type_id, :url, :secret_key)'; (:platform_id, :agent_type_id, :url, :secret_key, :check_period)';
$query = $this->db->prepare($sql); $query = $this->db->prepare($sql);
$query->execute([ $query->execute([
@ -65,6 +107,7 @@ class Agent {
':agent_type_id' => $newAgent['type_id'], ':agent_type_id' => $newAgent['type_id'],
':url' => $newAgent['url'], ':url' => $newAgent['url'],
':secret_key' => $newAgent['secret_key'], ':secret_key' => $newAgent['secret_key'],
':check_period' => $newAgent['check_period'],
]); ]);
return true; return true;
@ -80,7 +123,8 @@ class Agent {
$sql = 'UPDATE jilo_agents SET $sql = 'UPDATE jilo_agents SET
agent_type_id = :agent_type_id, agent_type_id = :agent_type_id,
url = :url, url = :url,
secret_key = :secret_key secret_key = :secret_key,
check_period = :check_period
WHERE WHERE
id = :agent_id id = :agent_id
AND AND
@ -91,6 +135,7 @@ class Agent {
':agent_type_id' => $updatedAgent['agent_type_id'], ':agent_type_id' => $updatedAgent['agent_type_id'],
':url' => $updatedAgent['url'], ':url' => $updatedAgent['url'],
':secret_key' => $updatedAgent['secret_key'], ':secret_key' => $updatedAgent['secret_key'],
':check_period' => $updatedAgent['check_period'],
':agent_id' => $updatedAgent['id'], ':agent_id' => $updatedAgent['id'],
':platform_id' => $platform_id, ':platform_id' => $platform_id,
]); ]);
@ -165,39 +210,64 @@ class Agent {
public function fetchAgent($agent_id, $force = false) { public function fetchAgent($agent_id, $force = false) {
// we need agent details for URL and JWT token // we need agent details for URL and JWT token
$agent = $this->getAgentDetails($agent_id); $agentDetails = $this->getAgentIDDetails($agent_id);
// Safe exit in case the agent is not found
if (empty($agentDetails)) {
return json_encode(['error' => 'Agent not found']);
}
$agent = $agentDetails[0];
$agent_cache_name = 'agent' . $agent_id . '_cache'; $agent_cache_name = 'agent' . $agent_id . '_cache';
$agent_cache_time = 'agent' . $agent_id . '_time'; $agent_cache_time = 'agent' . $agent_id . '_time';
// check if the cache is still valid, unless force-refresh is requested // check if the cache is still valid, unless force-refresh is requested
if (!$force && this->checkAgentCache($agent_id)) { if (!$force && $this->checkAgentCache($agent_id)) {
return $_SESSION[$agent_cache_name]; return $_SESSION[$agent_cache_name];
} }
// generate the JWT token
$payload = [
'agent_id' => $agent_id,
'timestamp' => time()
];
$jwt = $this->generateAgentToken($payload, $agent['secret_key']);
// Make the API request // Make the API request
$ch = curl_init(); $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $agent[0]['url']); curl_setopt($ch, CURLOPT_URL, $agent['url'] . $agent['agent_endpoint']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // timeout 10 seconds curl_setopt($ch, CURLOPT_TIMEOUT, 10); // timeout 10 seconds
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $jwt,
'Content-Type: application/json'
]);
$response = curl_exec($ch); $response = curl_exec($ch);
$curl_error = curl_error($ch); $curl_error = curl_error($ch);
$curl_errno = curl_errno($ch); $curl_errno = curl_errno($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); curl_close($ch);
// general curl error // curl error
if ($curl_error) { if ($curl_errno) {
return json_encode(['error' => 'curl error: ' . $curl_error]); return json_encode(['error' => 'curl error: ' . $curl_error]);
} }
// response is not 200 OK
if ($http_code !== 200) {
return json_encode(['error' => 'HTTP error: ' . $http_code]);
}
// other custom error(s) // other custom error(s)
if (strpos($response, 'Auth header not received') !== false) { if (strpos($response, 'Auth header not received') !== false) {
return json_encode(['error' => 'Auth header not received']); return json_encode(['error' => 'Auth header not received']);
} }
// Cache the result and the timestamp if the response is successful // Cache the result and the timestamp if the response is successful
$_SESSION[$agent_cache_name] = $response; // We decode it so that it's pure JSON and not escaped
$_SESSION[$agent_cache_name] = json_decode($response, true);
$_SESSION[$agent_cache_time] = time(); $_SESSION[$agent_cache_time] = time();
return $response; return $response;

View File

@ -0,0 +1,34 @@
<?php
class Server {
private $db;
public function __construct($database) {
$this->db = $database->getConnection();
}
// get Jilo Server status
public function getServerStatus($host = '127.0.0.1', $port = 8080, $endpoint = '/health') {
$url = "http://$host:$port$endpoint";
$options = [
'http' => [
'method' => 'GET',
'timeout' => 3,
],
];
$context = stream_context_create($options);
$response = @file_get_contents($url, false, $context);
// We check the response if it's 200 OK
if ($response !== false && isset($http_response_header) && strpos($http_response_header[0], '200 OK') !== false) {
return true;
}
// If it's not 200 OK
return false;
}
}
?>

View File

@ -38,6 +38,9 @@ if (isset($_POST['url'])) {
if (isset($_POST['secret_key'])) { if (isset($_POST['secret_key'])) {
$secret_key = htmlspecialchars($_POST['secret_key']); $secret_key = htmlspecialchars($_POST['secret_key']);
} }
if (isset($_POST['check_period'])) {
$check_period = htmlspecialchars($_POST['check_period']);
}
// platforms // platforms
if (isset($_POST['name'])) { if (isset($_POST['name'])) {

View File

@ -23,6 +23,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
'type_id' => $type, 'type_id' => $type,
'url' => $url, 'url' => $url,
'secret_key' => $secret_key, 'secret_key' => $secret_key,
'check_period' => $check_period,
]; ];
$result = $agentObject->addAgent($platform_id, $newAgent); $result = $agentObject->addAgent($platform_id, $newAgent);
if ($result === true) { if ($result === true) {
@ -61,6 +62,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
'agent_type_id' => $type, 'agent_type_id' => $type,
'url' => $url, 'url' => $url,
'secret_key' => $secret_key, 'secret_key' => $secret_key,
'check_period' => $check_period,
]; ];
$result = $agentObject->editAgent($platform_id, $updatedAgent); $result = $agentObject->editAgent($platform_id, $updatedAgent);
if ($result === true) { if ($result === true) {
@ -127,6 +129,8 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
switch ($action) { switch ($action) {
case 'add-agent': case 'add-agent':
$jilo_agent_types = $agentObject->getAgentTypes(); $jilo_agent_types = $agentObject->getAgentTypes();
$jilo_agents_in_platform = $agentObject->getPlatformAgentTypes($platform_id);
$jilo_agent_types_in_platform = array_column($jilo_agents_in_platform, 'agent_type_id');
include '../app/templates/config-add-agent.php'; include '../app/templates/config-add-agent.php';
break; break;
case 'add': case 'add':

View File

@ -42,7 +42,7 @@ try {
$_SESSION['notice'] = "Login successful"; $_SESSION['notice'] = "Login successful";
$user_id = $userObject->getUserId($username)[0]['id']; $user_id = $userObject->getUserId($username)[0]['id'];
$logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user'); $logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user');
header('Location: index.php'); header('Location: ' . htmlspecialchars($app_root));
exit(); exit();
// login failed // login failed
@ -50,7 +50,7 @@ try {
$_SESSION['error'] = "Login failed."; $_SESSION['error'] = "Login failed.";
$user_id = $userObject->getUserId($username)[0]['id']; $user_id = $userObject->getUserId($username)[0]['id'];
$logObject->insertLog($user_id, "Login: Failed login attempt for user \"$username\". IP: $user_IP", 'user'); $logObject->insertLog($user_id, "Login: Failed login attempt for user \"$username\". IP: $user_IP", 'user');
header('Location: index.php'); header('Location: ' . htmlspecialchars($app_root));
exit(); exit();
} }
} }

View File

@ -23,12 +23,12 @@ if ($config['registration_enabled'] === true) {
// redirect to login // redirect to login
if ($result === true) { if ($result === true) {
$_SESSION['notice'] = "Registration successful.<br />You can log in now."; $_SESSION['notice'] = "Registration successful.<br />You can log in now.";
header('Location: index.php'); header('Location: ' . htmlspecialchars($app_root));
exit(); exit();
// registration fail, redirect to login // registration fail, redirect to login
} else { } else {
$_SESSION['error'] = "Registration failed. $result"; $_SESSION['error'] = "Registration failed. $result";
header('Location: index.php'); header('Location: ' . htmlspecialchars($app_root));
exit(); exit();
} }
} }

View File

@ -0,0 +1,52 @@
<?php
// Jilo components status checks
//
require '../app/classes/agent.php';
$agentObject = new Agent($dbWeb);
include '../app/templates/status-server.php';
foreach ($platformsAll as $platform) {
include '../app/templates/status-platform.php';
$agentDetails = $agentObject->getAgentDetails($platform['id']);
foreach ($agentDetails as $agent) {
$agent_url = parse_url($agent['url']);
$agent_protocol = isset($agent_url['scheme']) ? $agent_url['scheme']: '';
$agent_host = isset($agent_url['host']) ? $agent_url['host']: '';
$agent_port = isset($agent_url['port']) ? $agent_url['port']: '';
// we get agent data to check availability
$agent_response = $agentObject->fetchAgent($agent['id'], true);
$agent_data = json_decode($agent_response);
if (json_last_error() === JSON_ERROR_NONE) {
$agent_availability = '<span class="text-warning">unknown</span>';
foreach ($agent_data as $key => $value) {
if ($key === 'error') {
$agent_availability = '<span class="text-danger">' . htmlspecialchars($value) . '</span>';
break;
}
if (preg_match('/_state$/', $key)) {
if ($value === 'error') {
$agent_availability = '<span class="text-danger">not running</span>';
break;
}
if ($value === 'running') {
$agent_availability = '<span class="text-success">running</span>';
break;
}
}
}
} else {
$agent_availability = 'json error';
}
include '../app/templates/status-agent.php';
}
}
?>

View File

@ -22,11 +22,13 @@
// print_r($_SESSION); // print_r($_SESSION);
?> ?>
<?php if (isset($_SESSION["agent{$agent['id']}_cache"])) { ?> <?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']) ?>-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']) ?>-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> <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> <span id="cacheInfo<?= htmlspecialchars($agent['id']) ?>" style="margin: 5px 0;"></span>
<?php } else { ?> <?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 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']) ?>-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> <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>

View File

@ -15,12 +15,15 @@
<select class="form-control" type="text" name="type" id="agent_type_id" required> <select class="form-control" type="text" name="type" id="agent_type_id" required>
<option></option> <option></option>
<?php foreach ($jilo_agent_types as $agent_type) { ?> <?php foreach ($jilo_agent_types as $agent_type) { ?>
<option value="<?= htmlspecialchars($agent_type['id']) ?>"> <option value="<?= htmlspecialchars($agent_type['id']) ?>"<?php
if (in_array($agent_type['id'], $jilo_agent_types_in_platform)) {
echo 'disabled="disabled"';
} ?>>
<?= htmlspecialchars($agent_type['description']) ?> <?= htmlspecialchars($agent_type['description']) ?>
</option> </option>
<?php } ?> <?php } ?>
</select> </select>
<p class="text-start"><small>type of agent (meet, jvb, jibri, all)</small></p> <p class="text-start"><small>type of agent (meet, jvb, jibri, etc.)<br />if a type has already been aded, it's disabled here</small></p>
</div> </div>
</div> </div>
@ -46,6 +49,17 @@
</div> </div>
</div> </div>
<div class="row mb-3">
<div class="col-md-4 text-end">
<label for="check_period" class="form-label">check period</label>
<span class="text-danger" style="margin-right: -12px;">*</span>
</div>
<div class="col-md-8">
<input class="form-control" type="text" name="check_period" value="0" required />
<p class="text-start"><small>period in minutes for the automatic agent check (0 disables it)</small></p>
</div>
</div>
<input type="hidden" name="new" value="true" /> <input type="hidden" name="new" value="true" />
<input type="hidden" name="item" value="agent" /> <input type="hidden" name="item" value="agent" />

View File

@ -46,6 +46,17 @@
</div> </div>
</div> </div>
<div class="row mb-3">
<div class="col-md-4 text-end">
<label for="check_period" class="form-label">check period</label>
<span class="text-danger" style="margin-right: -12px;">*</span>
</div>
<div class="col-md-8">
<input class="form-control" type="text" name="check_period" value="<?= htmlspecialchars($agentDetails[0]['check_period']) ?>" required />
<p class="text-start"><small>period in minutes for the automatic agent check (0 disables it)</small></p>
</div>
</div>
<br /> <br />
<input type="hidden" name="agent" value="<?= htmlspecialchars($agentDetails[0]['id']) ?>" /> <input type="hidden" name="agent" value="<?= htmlspecialchars($agentDetails[0]['id']) ?>" />

View File

@ -97,6 +97,16 @@ echo "\n";
<?= htmlspecialchars($agent_array['url'].$agent_array['agent_endpoint']) ?> <?= htmlspecialchars($agent_array['url'].$agent_array['agent_endpoint']) ?>
</div> </div>
</div> </div>
<?php if (isset($agent_array['check_period']) && $agent_array['check_period'] !== 0) { ?>
<div class="row mb-1" style="padding-left: 100px;">
<div class="col-md-4 text-end">
check period:
</div>
<div class="border col-md-8 text-start">
<?= htmlspecialchars($agent_array['check_period']) ?> <?= ($agent_array['check_period'] == 1 ? 'minute' : 'minutes') ?>
</div>
</div>
<?php } ?>
</div> </div>
</div> </div>
</div> </div>

View File

@ -38,6 +38,14 @@ It's a multi-user web tool with user levels and access rights integrated into it
The current website you are looking at is running a Jilo Web instance. The current website you are looking at is running a Jilo Web instance.
<hr /><strong>"Jilo Server"</strong>
Jilo Server is a server component written in Go, meant to work alongside Jilo Web. It is responsible for all automated tasks - health checks, periodic retrieval of data from the remote Jilo Agents, etc.
It generally works on the same machine as the web interface Jilo Web and shares its database, although if needed it could be deployed on a separate machine.
Jilo Web checks for the Jilo Server availability and displays a warning if there is a problem with the server.
</div> </div>
</div> </div>

View File

@ -78,6 +78,11 @@ $timeNow = new DateTime('now', new DateTimeZone($userTimezone));
</li> </li>
</a> </a>
<?php } ?> <?php } ?>
<a href="<?= htmlspecialchars($app_root) ?>?page=status">
<li class="list-group-item<?php if ($page === 'status' && $item === '') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
<i class="fas fa-heartbeat" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="status"></i>status
</li>
</a>
<?php if ($userObject->hasRight($user_id, 'view app logs')) {?> <?php if ($userObject->hasRight($user_id, 'view app logs')) {?>
<a href="<?= htmlspecialchars($app_root) ?>?page=logs"> <a href="<?= htmlspecialchars($app_root) ?>?page=logs">
<li class="list-group-item<?php if ($page === 'logs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>"> <li class="list-group-item<?php if ($page === 'logs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">

View File

@ -0,0 +1,14 @@
<!-- jilo agent status -->
<div class="card text-center w-75 mx-lef" style="padding-left: 80px;">
<div class="card-body">
<p class="card-text text-left" style="text-align: left;">
Jilo Agent <a href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform['id']) ?>agent<?= htmlspecialchars($agent['id']) ?>"><?= htmlspecialchars($agent['agent_description']) ?></a>:
<strong><?= $agent_availability ?></strong>
<br />
host: <strong><?= htmlspecialchars($agent_host) ?></strong>,
port: <strong><?= htmlspecialchars($agent_port) ?></strong>,
endpoint: <strong><?= htmlspecialchars($agent['agent_endpoint']) ?></strong>
</p>
</div>
</div>

View File

@ -0,0 +1,10 @@
<!-- jitsi platform status -->
<br />
<div class="card text-center w-75 mx-lef" style="padding-left: 40px;">
<div class="card-body">
<p class="card-text text-left" style="text-align: left;">
Jitsi Meet platform: <a href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform['id']) ?>"><?= htmlspecialchars($platform['name']) ?></a>
</p>
</div>
</div>

View File

@ -0,0 +1,19 @@
<!-- jilo status -->
<div class="card text-center w-75 mx-lef">
<p class="h4 card-header">Jilo platform status</p>
<div class="card-body">
<p class="card-text text-left" style="text-align: left;">
Jilo Server:
<?php if ($server_status) { ?>
<strong><span class="text-success">running</span></strong>
<?php } else { ?>
<strong><span class="text-danger">not running</span></strong>
<?php } ?>
<br />
host: <strong><?= htmlspecialchars($server_host) ?></strong>,
port: <strong><?= htmlspecialchars($server_port) ?></strong>,
endpoint: <strong><?= htmlspecialchars($server_endpoint) ?></strong>
</p>
</div>
</div>

View File

@ -41,6 +41,7 @@ $allowed_urls = [
'profile', 'profile',
'config', 'config',
'status',
'logs', 'logs',
'help', 'help',
@ -88,7 +89,7 @@ if (isset($_COOKIE['username'])) {
// redirect to login // redirect to login
if ( !isset($_COOKIE['username']) && ($page !== 'login' && $page !== 'register') ) { if ( !isset($_COOKIE['username']) && ($page !== 'login' && $page !== 'register') ) {
header('Location: index.php?page=login'); header('Location: ' . htmlspecialchars($app_root) . '?page=login');
exit(); exit();
} }
@ -145,6 +146,24 @@ if ($page == 'logout') {
$userDetails = $userObject->getUserDetails($user_id); $userDetails = $userObject->getUserDetails($user_id);
$userRights = $userObject->getUserRights($user_id); $userRights = $userObject->getUserRights($user_id);
$userTimezone = isset($userDetails[0]['timezone']) ? $userDetails[0]['timezone'] : 'UTC'; // Default to UTC if no timezone is set $userTimezone = isset($userDetails[0]['timezone']) ? $userDetails[0]['timezone'] : 'UTC'; // Default to UTC if no timezone is set
// If by error a logged in user requests the login page
if ($page === 'login') {
header('Location: ' . htmlspecialchars($app_root));
exit();
}
// check if the Jilo Server is running
require '../app/classes/server.php';
$serverObject = new Server($dbWeb);
$server_host = '127.0.0.1';
$server_port = '8080';
$server_endpoint = '/health';
$server_status = $serverObject->getServerStatus($server_host, $server_port, $server_endpoint);
if (!$server_status) {
$error = 'The Jilo Server is not running. Some data may be old and incorrect.';
}
} }
// page building // page building

View File

@ -0,0 +1,3 @@
<?php
phpinfo();
?>

View File

@ -58,24 +58,27 @@ function fetchData(agent_id, url, endpoint, jwtToken, force = false) {
// show the result in the html // show the result in the html
resultElement.innerHTML = JSON.stringify(result, null, 2); resultElement.innerHTML = JSON.stringify(result, null, 2);
// get the cache timestamp from the session // we don't cache the /status
const now = Date.now(); if (endpoint !== '/status') {
const cacheTimestamp = new Date(now); // get the cache timestamp from the session
const now = Date.now();
const cacheTimestamp = new Date(now);
// display the cache retrieval date and time // display the cache retrieval date and time
const formattedDate = cacheTimestamp.toLocaleDateString(); const formattedDate = cacheTimestamp.toLocaleDateString();
const formattedTime = cacheTimestamp.toLocaleTimeString(); const formattedTime = cacheTimestamp.toLocaleTimeString();
cacheInfoElement.style.display = ''; cacheInfoElement.style.display = '';
cacheInfoElement.innerHTML = `cache refreshed on ${formattedDate} at ${formattedTime}`; cacheInfoElement.innerHTML = `cache refreshed on ${formattedDate} at ${formattedTime}`;
// show the cache buttons // show the cache buttons
loadCacheButton.disabled = false; loadCacheButton.disabled = false;
loadCacheButton.style.display = ''; loadCacheButton.style.display = '';
clearCacheButton.disabled = false; clearCacheButton.disabled = false;
clearCacheButton.style.display = ''; clearCacheButton.style.display = '';
// send the result to PHP to store in session // send the result to PHP to store in session
saveResultToSession(result, agent_id); saveResultToSession(result, agent_id);
}
} }
} catch (e) { } catch (e) {
// Display the error // Display the error

View File

@ -140,6 +140,7 @@ html, body {
.main-content { .main-content {
flex-grow: 1; flex-grow: 1;
transition: width 0.5s ease; transition: width 0.5s ease;
margin-bottom: 50px;
/* width: 80%;*/ /* width: 80%;*/
} }
.main-content.expanded { .main-content.expanded {