Files
reflector-dashboard/auth/admin_nodeauth.php
T

129 lines
6.8 KiB
PHP

<?php
/*
* Reflector Dashboard — web front-end for SvxReflector
* Copyright (C) 2026 SA7AUX (Björn)
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version. See the LICENSE file for details.
*/
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 — Reflector Dashboard';
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';
?>