Adds simple admin-tools page
parent
f22fa76987
commit
a77cf5b328
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Admin tools controller
|
||||||
|
*
|
||||||
|
* Allows superusers to:
|
||||||
|
* - Enable/disable maintenance mode
|
||||||
|
* - Run database migrations
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Security and CSRF
|
||||||
|
require_once __DIR__ . '/../helpers/security.php';
|
||||||
|
$security = SecurityHelper::getInstance();
|
||||||
|
|
||||||
|
// Must be logged in
|
||||||
|
if (!Session::isValidSession()) {
|
||||||
|
header('Location: ' . $app_root . '?page=login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be superuser
|
||||||
|
$canAdmin = false;
|
||||||
|
if (isset($userId) && isset($userObject) && method_exists($userObject, 'hasRight')) {
|
||||||
|
$canAdmin = ($userId === 1) || (bool)$userObject->hasRight($userId, 'superuser');
|
||||||
|
}
|
||||||
|
if (!$canAdmin) {
|
||||||
|
Feedback::flash('SECURITY', 'PERMISSION_DENIED');
|
||||||
|
header('Location: ' . $app_root);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle actions
|
||||||
|
$action = $_POST['action'] ?? '';
|
||||||
|
if ($action !== '') {
|
||||||
|
if (!$security->verifyCsrfToken($_POST['csrf_token'] ?? '')) {
|
||||||
|
Feedback::flash('SECURITY', 'CSRF_INVALID');
|
||||||
|
header('Location: ' . $app_root . '?page=admin-tools');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($action === 'maintenance_on') {
|
||||||
|
require_once __DIR__ . '/../core/Maintenance.php';
|
||||||
|
$msg = trim($_POST['maintenance_message'] ?? '');
|
||||||
|
\App\Core\Maintenance::enable($msg);
|
||||||
|
Feedback::flash('NOTICE', 'DEFAULT', 'Maintenance mode enabled.', true);
|
||||||
|
} elseif ($action === 'maintenance_off') {
|
||||||
|
require_once __DIR__ . '/../core/Maintenance.php';
|
||||||
|
\App\Core\Maintenance::disable();
|
||||||
|
Feedback::flash('NOTICE', 'DEFAULT', 'Maintenance mode disabled.', true);
|
||||||
|
} elseif ($action === 'migrate_up') {
|
||||||
|
require_once __DIR__ . '/../core/MigrationRunner.php';
|
||||||
|
$migrationsDir = __DIR__ . '/../../doc/database/migrations';
|
||||||
|
$runner = new \App\Core\MigrationRunner($db, $migrationsDir);
|
||||||
|
$applied = $runner->applyPendingMigrations();
|
||||||
|
if (empty($applied)) {
|
||||||
|
Feedback::flash('NOTICE', 'DEFAULT', 'No pending migrations.', true);
|
||||||
|
} else {
|
||||||
|
Feedback::flash('NOTICE', 'DEFAULT', 'Applied migrations: ' . implode(', ', $applied), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Feedback::flash('ERROR', 'DEFAULT', 'Action failed: ' . $e->getMessage(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . $app_root . '?page=admin-tools');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare data for view
|
||||||
|
require_once __DIR__ . '/../core/Maintenance.php';
|
||||||
|
$maintenance_enabled = \App\Core\Maintenance::isEnabled();
|
||||||
|
$maintenance_message = \App\Core\Maintenance::getMessage();
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../core/MigrationRunner.php';
|
||||||
|
$migrationsDir = __DIR__ . '/../../doc/database/migrations';
|
||||||
|
$pending = [];
|
||||||
|
$applied = [];
|
||||||
|
try {
|
||||||
|
$runner = new \App\Core\MigrationRunner($db, $migrationsDir);
|
||||||
|
$pending = $runner->listPendingMigrations();
|
||||||
|
$applied = $runner->listAppliedMigrations();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
// show error in the page
|
||||||
|
$migration_error = $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF token
|
||||||
|
$csrf_token = $security->generateCsrfToken();
|
||||||
|
|
||||||
|
// Get any new feedback messages
|
||||||
|
include __DIR__ . '/../helpers/feedback.php';
|
||||||
|
|
||||||
|
// Load the template
|
||||||
|
include __DIR__ . '/../templates/admin-tools.php';
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
/** @var bool $maintenance_enabled */
|
||||||
|
/** @var string $maintenance_message */
|
||||||
|
/** @var array $pending */
|
||||||
|
/** @var array $applied */
|
||||||
|
/** @var string $csrf_token */
|
||||||
|
?>
|
||||||
|
<div class="container mt-4">
|
||||||
|
<h2>Admin tools</h2>
|
||||||
|
<p class="text-muted">System maintenance and database utilities.</p>
|
||||||
|
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Maintenance mode</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>Status: <strong class="<?= $maintenance_enabled ? 'text-danger' : 'text-success' ?>">
|
||||||
|
<?= $maintenance_enabled ? 'Enabled' : 'Disabled' ?></strong></p>
|
||||||
|
<form method="post" class="mb-2">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf_token) ?>">
|
||||||
|
<input type="hidden" name="action" value="maintenance_on">
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="maintenance_message" class="form-label">Message (optional)</label>
|
||||||
|
<input type="text" id="maintenance_message" name="maintenance_message" class="form-control" value="<?= htmlspecialchars($maintenance_message) ?>" placeholder="Upgrading database">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-warning" <?= $maintenance_enabled ? 'disabled' : '' ?>>Enable maintenance</button>
|
||||||
|
</form>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf_token) ?>">
|
||||||
|
<input type="hidden" name="action" value="maintenance_off">
|
||||||
|
<button type="submit" class="btn btn-secondary" <?= $maintenance_enabled ? '' : 'disabled' ?>>Disable maintenance</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Database migrations</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<?php if (!empty($migration_error)): ?>
|
||||||
|
<div class="alert alert-danger">Error: <?= htmlspecialchars($migration_error) ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<p>
|
||||||
|
<strong>Pending (<?= count($pending) ?>):</strong>
|
||||||
|
<?php if (empty($pending)): ?>
|
||||||
|
<span class="text-success">None</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<code><?= htmlspecialchars(implode(', ', $pending)) ?></code>
|
||||||
|
<?php endif; ?>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Applied (<?= count($applied) ?>):</strong>
|
||||||
|
<?php if (empty($applied)): ?>
|
||||||
|
<span class="text-muted">None</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<code><?= htmlspecialchars(implode(', ', $applied)) ?></code>
|
||||||
|
<?php endif; ?>
|
||||||
|
</p>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf_token) ?>">
|
||||||
|
<input type="hidden" name="action" value="migrate_up">
|
||||||
|
<button type="submit" class="btn btn-primary" <?= empty($pending) ? 'disabled' : '' ?>>Apply pending migrations</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -69,8 +69,13 @@
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<h6 class="dropdown-header">system</h6>
|
<h6 class="dropdown-header">system</h6>
|
||||||
<?php if ($userObject->hasRight($userId, 'superuser') ||
|
<?php if ($userObject->hasRight($userId, 'superuser')) {?>
|
||||||
$userObject->hasRight($userId, 'view config file')) {?>
|
<a class="dropdown-item" href="<?= htmlspecialchars($app_root) ?>?page=admin-tools">
|
||||||
|
<i class="fas fa-toolbox"></i>Admin tools
|
||||||
|
</a>
|
||||||
|
<?php } ?>
|
||||||
|
<?php if ($userObject->hasRight($userId, 'superuser') ||
|
||||||
|
$userObject->hasRight($userId, 'view config file')) {?>
|
||||||
<a class="dropdown-item" href="<?= htmlspecialchars($app_root) ?>?page=config">
|
<a class="dropdown-item" href="<?= htmlspecialchars($app_root) ?>?page=config">
|
||||||
<i class="fas fa-wrench"></i>Configuration
|
<i class="fas fa-wrench"></i>Configuration
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -146,6 +146,7 @@ $allowed_urls = [
|
||||||
'graphs','latest','livejs','agents',
|
'graphs','latest','livejs','agents',
|
||||||
'profile','credentials','config','security',
|
'profile','credentials','config','security',
|
||||||
'settings','theme','theme-asset',
|
'settings','theme','theme-asset',
|
||||||
|
'admin-tools',
|
||||||
'status',
|
'status',
|
||||||
'help','about',
|
'help','about',
|
||||||
'login','logout',
|
'login','logout',
|
||||||
|
|
Loading…
Reference in New Issue