Files
portspoof_concentrator/nodes.php
2026-03-13 16:30:09 -04:00

177 lines
5.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/includes/auth.php';
require_login();
require_once __DIR__ . '/includes/functions.php';
$errors = [];
$success = '';
// ── Handle POST ───────────────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'delete') {
$id = (int)($_POST['id'] ?? 0);
if ($id > 0) {
delete_node($id);
$success = 'Node deleted.';
}
} elseif (in_array($action, ['add', 'edit'], true)) {
$id = $action === 'edit' ? (int)($_POST['id'] ?? 0) : null;
$data = [
'name' => trim($_POST['name'] ?? ''),
'api_url' => rtrim(trim($_POST['api_url'] ?? ''), '/'),
'username' => trim($_POST['username'] ?? 'admin'),
'password' => $_POST['password'] ?? '',
'verify_ssl' => isset($_POST['verify_ssl']) ? 1 : 0,
'enabled' => isset($_POST['enabled']) ? 1 : 0,
];
if ($data['name'] === '') $errors[] = 'Name is required.';
if ($data['api_url'] === '') $errors[] = 'API URL is required.';
if ($data['password'] === '' && $action === 'add') $errors[] = 'Password is required.';
// On edit, keep existing password if field left blank
if ($action === 'edit' && $data['password'] === '') {
$existing = get_node($id);
$data['password'] = $existing['password'] ?? '';
}
if (empty($errors)) {
upsert_node($data, $id);
$success = $action === 'add' ? 'Node added.' : 'Node updated.';
}
}
}
$nodes = get_all_nodes();
$edit_node = null;
if (isset($_GET['edit'])) {
$edit_node = get_node((int)$_GET['edit']);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nodes portspoof concentrator</title>
<style>
<?php include __DIR__ . '/includes/style.php'; ?>
</style>
<script>document.documentElement.setAttribute('data-theme',localStorage.getItem('theme')||'dark')</script>
</head>
<body>
<header>
<h1>portspoof<span>concentrator</span></h1>
<nav>
<a href="index.php">Dashboard</a>
<a href="nodes.php" class="active">Nodes</a>
<a href="settings.php">Settings</a>
<?php if (auth_enabled()): ?>
<a href="logout.php" style="color:var(--muted)">Sign out</a>
<?php endif; ?>
<?php include __DIR__ . '/includes/theme_toggle.php'; ?>
</nav>
</header>
<main>
<?php if ($success): ?>
<div class="alert ok"><?= h($success) ?></div>
<?php endif; ?>
<?php foreach ($errors as $e): ?>
<div class="alert err"><?= h($e) ?></div>
<?php endforeach; ?>
<section class="card">
<h2><?= $edit_node ? 'Edit node' : 'Add node' ?></h2>
<form method="post">
<input type="hidden" name="action" value="<?= $edit_node ? 'edit' : 'add' ?>">
<?php if ($edit_node): ?>
<input type="hidden" name="id" value="<?= (int)$edit_node['id'] ?>">
<?php endif; ?>
<label>Name
<input type="text" name="name" required
value="<?= h($edit_node['name'] ?? '') ?>">
</label>
<label>API URL &nbsp;<small>e.g. https://192.168.1.10:8080</small>
<input type="url" name="api_url" required
value="<?= h($edit_node['api_url'] ?? '') ?>">
</label>
<label>Username
<input type="text" name="username"
value="<?= h($edit_node['username'] ?? 'admin') ?>">
</label>
<label>Password <?= $edit_node ? '<small>(leave blank to keep current)</small>' : '' ?>
<input type="password" name="password" <?= $edit_node ? '' : 'required' ?>>
</label>
<label class="inline">
<input type="checkbox" name="verify_ssl"
<?= ($edit_node['verify_ssl'] ?? 0) ? 'checked' : '' ?>>
Verify SSL certificate
</label>
<label class="inline">
<input type="checkbox" name="enabled"
<?= ($edit_node['enabled'] ?? 1) ? 'checked' : '' ?>>
Enabled
</label>
<button type="submit"><?= $edit_node ? 'Save changes' : 'Add node' ?></button>
<?php if ($edit_node): ?>
&nbsp;<a href="nodes.php">Cancel</a>
<?php endif; ?>
</form>
</section>
<section class="card">
<h2>Configured nodes</h2>
<?php if (empty($nodes)): ?>
<p class="muted">No nodes yet. Add one above.</p>
<?php else: ?>
<table>
<thead>
<tr>
<th>Name</th>
<th>API URL</th>
<th>SSL verify</th>
<th>Enabled</th>
<th>Last fetched</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($nodes as $n): ?>
<tr>
<td><?= h($n['name']) ?></td>
<td><code><?= h($n['api_url']) ?></code></td>
<td><?= $n['verify_ssl'] ? 'yes' : 'no' ?></td>
<td><?= $n['enabled'] ? '<span class="badge ok">yes</span>' : '<span class="badge">no</span>' ?></td>
<td><?= $n['last_fetched_at'] ? h($n['last_fetched_at']) : '<span class="muted">never</span>' ?></td>
<td class="actions">
<a href="nodes.php?edit=<?= (int)$n['id'] ?>">edit</a>
<form method="post" style="display:inline"
onsubmit="return confirm('Delete node <?= h(addslashes($n['name'])) ?>?')">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= (int)$n['id'] ?>">
<button type="submit" class="link-btn danger">delete</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</section>
</main>
<?php include __DIR__ . '/includes/footer.php'; ?>
</body>
</html>