177 lines
5.7 KiB
PHP
177 lines
5.7 KiB
PHP
<?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 <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): ?>
|
||
<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>
|