<?php if (!defined('DASHBOARD_ROOT')) { http_response_code(403); exit; } require_once DASHBOARD_ROOT . '/system/gateway_sync.php'; $fleetMsg = ''; $pingResult = null; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['fleet_action'])) { CSRF::enforce(); RBAC::enforce('manage.settings'); if ($_POST['fleet_action'] === 'set_password') { $newPass = $_POST['hop_password'] ?? ''; if (strlen($newPass) >= 8) { if (GatewaySync::setHopPassword($newPass)) { Events::record(Events::CAT_MODIFY, 'fleet.hop_password_updated', 'settings', null); $fleetMsg = 'ok'; } else { $fleetMsg = 'err'; } } else { $fleetMsg = 'short'; } } if ($_POST['fleet_action'] === 'test_hops') { $pingResult = GatewaySync::ping(); } } $hasPassword = false; try { $row = Database::fetchOne("SELECT id FROM settings WHERE setting_key = 'fleet_hop_password'"); $hasPassword = (bool)$row; } catch (\Throwable $e) {} ?> <div id="fleet-sync-content" style="max-width:600px;padding:20px 0"> <h3 style="font-size:13px;font-weight:900;text-transform:uppercase;letter-spacing:2px;color:rgba(200,204,212,.5);margin:0 0 20px">Fleet Relay Authentication</h3> <p style="font-size:12px;color:rgba(200,204,212,.4);margin-bottom:20px;line-height:1.6"> The gateway sync uses a 3-hop SSH relay: <strong style="color:#3498db">Origin → Shield → Filter → Proxy</strong>.<br> Set the shared admin password used to authenticate at each hop. </p><?php if ($fleetMsg === 'ok'): ?> <div class="toast toast-ok" style="margin-bottom:16px">✓ Hop password updated and encrypted.</div><?php elseif ($fleetMsg === 'err'): ?> <div class="toast toast-del" style="margin-bottom:16px">✕ Failed to save password.</div><?php elseif ($fleetMsg === 'short'): ?> <div class="toast toast-del" style="margin-bottom:16px">✕ Password must be at least 8 characters.</div><?php endif; ?> <form method="POST" style="margin-bottom:24px"><?= CSRF::field() ?> <input type="hidden" name="fleet_action" value="set_password"> <div style="display:grid;grid-template-columns:1fr auto;gap:12px;align-items:end"> <div> <label style="display:block;font-size:10px;font-weight:900;letter-spacing:1.5px;text-transform:uppercase;color:rgba(200,204,212,.5);margin-bottom:6px"> Fleet Hop Password<?= $hasPassword ? '<span style="color:#2ecc71">● SET</span>' : '<span style="color:#e74c3c">● NOT SET</span>' ?> </label> <input type="password" name="hop_password" placeholder="<?= $hasPassword ? '••••••••' : 'Enter fleet password' ?> " style="width:100%;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:10px;color:#fff;padding:10px 14px;font-family:inherit;font-size:13px" required minlength="8"> </div> <button type="submit" class="btn-primary" style="padding:10px 20px;white-space:nowrap">UPDATE</button> </div> </form> <form method="POST" style="margin-bottom:16px"><?= CSRF::field() ?> <input type="hidden" name="fleet_action" value="test_hops"> <button type="submit" style="padding:10px 20px;border-radius:10px;font-size:11px;font-weight:800;letter-spacing:1px;background:rgba(52,152,219,.08);color:#3498db;border:1px solid rgba(52,152,219,.15);cursor:pointer;transition:all .2s"> 🔍 TEST HOP CONNECTIVITY </button> </form><?php if ($pingResult !== null): ?> <div style="margin-top:16px;padding:16px;border-radius:12px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04)"> <div style="font-size:10px;font-weight:900;letter-spacing:1.5px;text-transform:uppercase;color:rgba(200,204,212,.5);margin-bottom:12px">Hop Test Results</div><?php foreach ($pingResult['reachable'] ?? [] as $hop => $ok): ?> <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"> <span style="width:8px;height:8px;border-radius:50%;background:<?= $ok ? '#2ecc71' : '#e74c3c' ?> "></span> <span style="font-size:12px;font-weight:700;color:<?= $ok ? '#2ecc71' : '#e74c3c' ?> "><?= htmlspecialchars($hop) ?> </span> <span style="font-size:10px;color:rgba(200,204,212,.3)"><?= $ok ? 'Connected' : 'Unreachable' ?> </span> </div><?php endforeach; ?> </div><?php endif; ?> <div style="margin-top:24px;padding:16px;border-radius:12px;background:rgba(230,168,23,.04);border:1px solid rgba(230,168,23,.1)"> <div style="font-size:10px;font-weight:900;letter-spacing:1.5px;text-transform:uppercase;color:rgba(230,168,23,.6);margin-bottom:8px">⚠ Security Note</div> <p style="font-size:11px;color:rgba(200,204,212,.4);line-height:1.5;margin:0"> This password is encrypted in the database and used only for automated relay hops through the WireGuard mesh. All hops use internal WG IPs — no public internet routes. Ensure all 3 nodes (Shield, Filter, Proxy) accept this password for the admin user. </p> </div> </div> <script nonce="<?= $cspNonce ?>"> (function(){ var content = document.getElementById('fleet-sync-content'); var panel = document.getElementById('panel-fleet'); if (content && panel) { panel.appendChild(content); } })(); </script>