jilo-web/public_html/index.php

325 lines
11 KiB
PHP
Raw Permalink Normal View History

<?php
2024-07-01 09:45:07 +00:00
/**
* Jilo web logs observer
*
* Description: A web interface to Jilo (JItsi Logs Observer), written in PHP
* Author: Yasen Pramatarov
* License: GPLv2
* Project URL: https://lindeas.com/jilo
2025-01-15 17:06:12 +00:00
* Year: 2024-2025
2025-04-12 14:21:34 +00:00
* Version: 0.4
2024-07-01 09:45:07 +00:00
*/
// error reporting, comment out in production
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
// Preparing plugins and hooks
// Initialize HookDispatcher and plugin system
require_once __DIR__ . '/../app/core/HookDispatcher.php';
require_once __DIR__ . '/../app/core/PluginManager.php';
use App\Core\HookDispatcher;
use App\Core\PluginManager;
// Global allowed URLs registration
register_hook('filter_allowed_urls', function($urls) {
if (isset($GLOBALS['plugin_controllers']) && is_array($GLOBALS['plugin_controllers'])) {
foreach ($GLOBALS['plugin_controllers'] as $controllers) {
foreach ($controllers as $ctrl) {
$urls[] = $ctrl;
}
}
}
return $urls;
});
// Hook registration and dispatch helpers
function register_hook(string $hook, callable $callback): void {
HookDispatcher::register($hook, $callback);
}
function do_hook(string $hook, array $context = []): void {
HookDispatcher::dispatch($hook, $context);
}
function filter_public_pages(array $pages): array {
return HookDispatcher::applyFilters('filter_public_pages', $pages);
}
function filter_allowed_urls(array $urls): array {
return HookDispatcher::applyFilters('filter_allowed_urls', $urls);
}
// Load enabled plugins
$plugins_dir = dirname(__DIR__) . '/plugins/';
$enabled_plugins = PluginManager::load($plugins_dir);
$GLOBALS['enabled_plugins'] = $enabled_plugins;
// Define CSRF token include path globally
if (!defined('CSRF_TOKEN_INCLUDE')) {
define('CSRF_TOKEN_INCLUDE', dirname(__DIR__) . '/app/includes/csrf_token.php');
}
// Global cnstants
require_once '../app/includes/constants.php';
// we start output buffering and
2024-08-19 10:25:09 +00:00
// flush it later only when there is no redirect
ob_start();
2025-04-13 16:34:13 +00:00
// Start session before any session-dependent code
require_once '../app/classes/session.php';
Session::startSession();
// Define page variable early via sanitize
require_once __DIR__ . '/../app/includes/sanitize.php';
// Ensure $page is defined to avoid undefined variable
if (!isset($page)) {
$page = 'dashboard';
}
// Middleware pipeline for security, sanitization & CSRF
require_once __DIR__ . '/../app/core/MiddlewarePipeline.php';
$pipeline = new \App\Core\MiddlewarePipeline();
$pipeline->add(function() {
// Apply security headers
require_once __DIR__ . '/../app/includes/security_headers_middleware.php';
return true;
});
2024-10-04 08:36:45 +00:00
2025-04-13 16:34:13 +00:00
// Check session validity
$validSession = Session::isValidSession();
2025-01-30 16:48:46 +00:00
// Get user ID early if session is valid
$userId = $validSession ? Session::getUserId() : null;
2025-02-17 12:36:00 +00:00
// Initialize feedback message system
require_once '../app/classes/feedback.php';
$system_messages = [];
require '../app/includes/errors.php';
2024-07-01 09:45:07 +00:00
// list of available pages
// edit accordingly, add 'pages/PAGE.php'
$allowed_urls = [
2024-09-13 11:02:59 +00:00
'dashboard',
'conferences','participants','components',
'graphs','latest','livejs','agents',
'profile','credentials','config','security',
'settings',
2024-10-19 13:09:16 +00:00
'status',
'help','about',
'login','logout',
2024-07-01 09:45:07 +00:00
];
// Let plugins filter/extend allowed_urls
$allowed_urls = filter_allowed_urls($allowed_urls);
require_once __DIR__ . '/../app/core/ConfigLoader.php';
use App\Core\ConfigLoader;
// Load configuration
$config = ConfigLoader::loadConfig([
2024-08-12 11:12:24 +00:00
__DIR__ . '/../app/config/jilo-web.conf.php',
2024-08-01 08:20:31 +00:00
__DIR__ . '/../jilo-web.conf.php',
'/srv/jilo-web/jilo-web.conf.php',
'/opt/jilo-web/jilo-web.conf.php',
]);
2025-04-24 11:30:35 +00:00
// Expose config file path for pages
$config_file = ConfigLoader::getConfigPath();
$localConfigPath = str_replace(__DIR__ . '/..', '', $config_file);
2024-07-01 09:45:07 +00:00
2024-10-04 15:13:55 +00:00
$app_root = $config['folder'];
2025-04-13 16:34:13 +00:00
// List of pages that don't require authentication
2025-04-17 07:30:34 +00:00
$public_pages = ['login', 'help', 'about'];
2025-04-13 16:34:13 +00:00
// Let plugins filter/extend public_pages
$public_pages = filter_public_pages($public_pages);
// Dispatch routing and auth
require_once __DIR__ . '/../app/core/Router.php';
use App\Core\Router;
$currentUser = Router::checkAuth($config, $app_root, $public_pages, $page);
// Connect to DB via DatabaseConnector
require_once __DIR__ . '/../app/core/DatabaseConnector.php';
use App\Core\DatabaseConnector;
$db = DatabaseConnector::connect($config);
// Logging: default to NullLogger, plugin can override
require_once __DIR__ . '/../app/core/NullLogger.php';
use App\Core\NullLogger;
$logObject = new NullLogger();
// Get the user IP
require_once __DIR__ . '/../app/helpers/ip_helper.php';
$user_IP = '';
// Plugin: initialize logging system plugin if available
do_hook('logger.system_init', ['db' => $db]);
// Override defaults if plugin provided real logger
if (isset($GLOBALS['logObject'])) {
$logObject = $GLOBALS['logObject'];
}
if (isset($GLOBALS['user_IP'])) {
$user_IP = $GLOBALS['user_IP'];
}
2024-09-16 14:09:37 +00:00
// CSRF middleware and run pipeline
$pipeline->add(function() {
// Initialize security middleware
require_once __DIR__ . '/../app/includes/csrf_middleware.php';
require_once __DIR__ . '/../app/helpers/security.php';
$security = SecurityHelper::getInstance();
// Verify CSRF token for POST requests
return applyCsrfMiddleware();
});
$pipeline->add(function() {
// Init rate limiter
global $db, $page, $userId;
require_once __DIR__ . '/../app/includes/rate_limit_middleware.php';
return checkRateLimit($db, $page, $userId);
});
$pipeline->add(function() {
// Init user functions
global $db, $userObject;
require_once __DIR__ . '/../app/classes/user.php';
include __DIR__ . '/../app/helpers/profile.php';
$userObject = new User($db);
return true;
});
if (!$pipeline->run()) {
exit;
}
// get platforms details
require '../app/classes/platform.php';
$platformObject = new Platform($db);
$platformsAll = $platformObject->getPlatformDetails();
2024-08-17 08:20:08 +00:00
// by default we connect ot the first configured platform
2024-10-04 08:36:45 +00:00
if ($platform_id == '') {
$platform_id = $platformsAll[0]['id'];
}
$platformDetails = $platformObject->getPlatformDetails($platform_id);
2024-08-17 08:20:08 +00:00
// logout is a special case, as we can't use session vars for notices
if ($page == 'logout') {
// clean up session
2025-04-13 16:34:13 +00:00
Session::destroySession();
2025-01-30 16:48:46 +00:00
// start new session for the login page
2025-04-13 16:34:13 +00:00
Session::startSession();
2025-01-30 16:48:46 +00:00
setcookie('username', "", time() - 100, $config['folder'], $config['domain'], isset($_SERVER['HTTPS']), true);
// Log successful logout
2025-04-27 16:00:58 +00:00
$logObject->log('info', "Logout: User \"$currentUser\" logged out. IP: $user_IP", ['user_id' => $userId, 'scope' => 'user']);
2024-09-30 09:52:06 +00:00
// Set success message
2025-02-16 08:18:26 +00:00
Feedback::flash('LOGIN', 'LOGOUT_SUCCESS');
2025-01-04 10:30:44 +00:00
include '../app/templates/page-header.php';
include '../app/templates/page-menu.php';
include '../app/pages/login.php';
2025-02-10 17:18:15 +00:00
include '../app/templates/page-footer.php';
2025-01-04 10:30:44 +00:00
} else {
// if user is logged in, we need user details and rights
2025-04-13 16:34:13 +00:00
if ($validSession) {
2024-10-23 12:28:45 +00:00
// If by error a logged in user requests the login page
if ($page === 'login') {
header('Location: ' . htmlspecialchars($app_root));
exit();
}
$userDetails = $userObject->getUserDetails($userId);
$userRights = $userObject->getUserRights($userId);
$userTimezone = (!empty($userDetails[0]['timezone'])) ? $userDetails[0]['timezone'] : 'UTC'; // Default to UTC if no timezone is set (or is missing)
2024-10-23 12:28:45 +00:00
2024-10-23 12:13:01 +00:00
// check if the Jilo Server is running
require '../app/classes/server.php';
$serverObject = new Server($db);
2024-10-23 12:13:01 +00:00
$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) {
2025-02-16 08:18:26 +00:00
Feedback::flash('ERROR', 'DEFAULT', 'The Jilo Server is not running. Some data may be old and incorrect.', false, true);
2024-10-23 12:13:01 +00:00
}
2024-10-18 12:41:15 +00:00
}
// --- Plugin loading logic for all enabled plugins ---
// Ensure all enabled plugin bootstraps are loaded before mapping controllers
foreach ($GLOBALS['enabled_plugins'] as $plugin_name => $plugin_info) {
$bootstrap_path = $plugin_info['path'] . '/bootstrap.php';
if (file_exists($bootstrap_path)) {
require_once $bootstrap_path;
}
}
// Plugin controller mapping logic (we add each controller listed in bootstrap as a page)
$mapped_plugin_controllers = [];
foreach ($GLOBALS['enabled_plugins'] as $plugin_name => $plugin_info) {
if (isset($GLOBALS['plugin_controllers'][$plugin_name])) {
foreach ($GLOBALS['plugin_controllers'][$plugin_name] as $plugin_page) {
$controller_path = $plugin_info['path'] . '/controllers/' . $plugin_page . '.php';
if (file_exists($controller_path)) {
$mapped_plugin_controllers[$plugin_page] = $controller_path;
}
}
}
}
// page building
if (in_array($page, $allowed_urls)) {
// The page is in allowed URLs
if (isset($mapped_plugin_controllers[$page]) && file_exists($mapped_plugin_controllers[$page])) {
// The page is from a plugin controller
if (defined('PLUGIN_PAGE_DIRECT_OUTPUT') && PLUGIN_PAGE_DIRECT_OUTPUT === true) {
// Barebone page controller, we don't output anything extra
include $mapped_plugin_controllers[$page];
ob_end_flush();
exit;
} else {
include '../app/templates/page-header.php';
include '../app/templates/page-menu.php';
if ($validSession) {
include '../app/templates/page-sidebar.php';
}
include $mapped_plugin_controllers[$page];
include '../app/templates/page-footer.php';
}
} else {
// The page is from a core controller
include '../app/templates/page-header.php';
include '../app/templates/page-menu.php';
if ($validSession) {
include '../app/templates/page-sidebar.php';
}
if (file_exists("../app/pages/{$page}.php")) {
include "../app/pages/{$page}.php";
} else {
include '../app/templates/error-notfound.php';
}
include '../app/templates/page-footer.php';
}
2024-07-01 09:45:07 +00:00
} else {
// The page is not in allowed URLs
include '../app/templates/page-header.php';
include '../app/templates/page-menu.php';
if ($validSession) {
include '../app/templates/page-sidebar.php';
}
2024-09-13 11:02:59 +00:00
include '../app/templates/error-notfound.php';
include '../app/templates/page-footer.php';
2024-08-06 07:40:52 +00:00
}
}
2024-08-19 10:25:09 +00:00
// flush the output buffer and show the page
ob_end_flush();
2024-07-01 09:45:07 +00:00
// clear errors and notices before next page just in case
unset($_SESSION['error']);
unset($_SESSION['notice']);