Stripped from the internal repo: per-box deploy trees, Go services (nodelist/astmeta/proxy/svxdr), deploy/sync scripts and all secrets. Config templates for nginx, PHP-FPM, Redis and tmpfiles live in install/ with CHANGEME placeholders. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
119 lines
6.3 KiB
PHP
119 lines
6.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require __DIR__ . '/lib.php';
|
|
start_session();
|
|
$uuid = $_SESSION['uid'] ?? null;
|
|
if (!is_string($uuid) || $uuid === '') { header('Location: /'); exit; }
|
|
$me = acct_get($uuid);
|
|
$lvl = acct_admin_level($uuid);
|
|
if ($lvl < 2) { header('Location: /'); exit; }
|
|
|
|
$page_title = 'Admin · Node Auth — SvxPortal';
|
|
require __DIR__ . '/header.php';
|
|
?>
|
|
<div class="container py-4" style="max-width:900px;">
|
|
|
|
<!-- Node list -->
|
|
<div id="naListPanel">
|
|
<div class="panel">
|
|
<div class="d-flex justify-content-between align-items-center mb-3 gap-2 flex-wrap">
|
|
<h5 class="mb-0">Node Authentication</h5>
|
|
<button type="button" class="btn btn-primary btn-sm" id="naBtnShowAdd">+ Add node</button>
|
|
</div>
|
|
<div id="naMsg" class="small mb-2" style="display:none;"></div>
|
|
<div style="overflow-x:auto; -webkit-overflow-scrolling:touch;">
|
|
<table class="data-table" id="naTable" style="min-width:640px;">
|
|
<thead><tr><th>Callsign</th><th>Auth</th><th>Admins</th><th>Cert email</th><th>Valid to</th><th>Actions</th></tr></thead>
|
|
<tbody><tr><td colspan="6" class="text-secondary">Loading…</td></tr></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="naStatus" class="text-secondary small mt-2"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add node -->
|
|
<div id="naAddPanel" style="display:none;">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h5 class="mb-0">Add node</h5>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="naBtnAddBack">Back to list</button>
|
|
</div>
|
|
<div class="panel">
|
|
<div class="small text-secondary mb-3">Login/password node. Cert nodes are added under <a href="/auth/admin_certs.php">Certificates</a> (linked by the certificate's email); their admins are managed from the node list.</div>
|
|
|
|
<label class="form-label small text-secondary mb-1" for="naNewNode">Login (node callsign, with -SSID)</label>
|
|
<input type="text" class="form-control form-control-sm mono mb-3" id="naNewNode" placeholder="SA7ABC-1" style="width:180px; text-transform:uppercase;">
|
|
|
|
<label class="form-label small text-secondary mb-1" for="naNewPw">Password</label>
|
|
<div class="d-flex gap-2 align-items-center flex-wrap mb-1">
|
|
<input type="text" class="form-control form-control-sm mono" id="naNewPw" style="width:240px;">
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="naNewPwGen">Generate</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="naNewPwCopy">Copy</button>
|
|
</div>
|
|
<div class="small text-secondary mb-3">Auto-generated. Goes in the node's <span class="mono">AUTH_KEY</span>; the node's admins see it in clear text under their profile → Nodes.</div>
|
|
|
|
<label class="form-label small text-secondary">Node admins</label>
|
|
<div class="small text-secondary mb-2">Callsigns that may administer this node and see its password. The node's own callsign always counts; add others here.</div>
|
|
<div class="d-flex gap-2 mb-2"><button type="button" class="btn btn-sm btn-outline-success" id="naAddAdmBtn">Add admin</button></div>
|
|
<div id="naAddAdmWrap" class="mb-3"></div>
|
|
|
|
<button type="button" class="btn btn-primary btn-sm" id="naBtnAdd">Create node</button>
|
|
<div id="naAddMsg" class="small mt-2" style="display:none;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit node -->
|
|
<div id="naEditPanel" style="display:none;">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h5 class="mb-0">Edit: <span id="naEditCs" class="mono"></span></h5>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="naBtnBack">Back to list</button>
|
|
</div>
|
|
<div class="panel">
|
|
<div class="small mb-3"><span class="text-secondary">Auth:</span> <span id="naEditType"></span></div>
|
|
|
|
<label class="form-label small text-secondary">Linked account</label>
|
|
<div id="naEditAcct" class="small mb-3">Loading…</div>
|
|
|
|
<div id="naEditPwWrap" style="display:none;">
|
|
<label class="form-label small text-secondary">Password (goes in the node's <span class="mono">AUTH_KEY</span>)</label>
|
|
<div class="d-flex gap-2 align-items-center flex-wrap mb-1">
|
|
<input type="text" class="form-control form-control-sm mono" id="naEditPw" style="width:240px;">
|
|
<button type="button" class="btn btn-primary btn-sm" id="naBtnPwSave">Save</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="naBtnPwGen">Generate new</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="naBtnPwCopy">Copy</button>
|
|
</div>
|
|
<div id="naPwMsg" class="small mb-3" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div id="naEditCertWrap" style="display:none;">
|
|
<label class="form-label small text-secondary">Certificate</label>
|
|
<div id="naEditCert" class="small mb-3"></div>
|
|
</div>
|
|
|
|
<label class="form-label small text-secondary">Node admins</label>
|
|
<div class="small text-secondary mb-2">Add a callsign to give them admin rights on this node. Each node has its own admins.</div>
|
|
<div id="naEditAdmins"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- One-time password modal (after Add) -->
|
|
<div class="modal fade" id="naPwModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content" style="background:#111; border:1px solid var(--line);">
|
|
<div class="modal-header" style="border-color:var(--line);">
|
|
<h5 class="modal-title" id="naPwTitle">Node password</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="small text-secondary mb-2">Copy this password into the node's <span class="mono">svxlink.conf</span> (<span class="mono">AUTH_KEY</span>). The node's owner and admins can also view it under profile → My Nodes.</div>
|
|
<div class="mono" id="naPwValue" style="font-size:1.1rem; word-break:break-all;"></div>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary mt-2" id="naPwCopy">Copy</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
$extra_scripts = '<script>var ADMIN_LEVEL = ' . $lvl . ';</script><script src="/auth/admin_nodeauth.js?v=' . @filemtime(__DIR__ . '/admin_nodeauth.js') . '"></script>';
|
|
require __DIR__ . '/footer.php';
|
|
?>
|