Files
reflector-dashboard/auth/my_nodes.php
T
bjorneandClaude Fable 5.1 25b481e2ae Public web-only release: SvxPortal front-end + auth backend, install templates and INSTALL.md
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>
2026-09-26 23:07:05 +02:00

77 lines
2.4 KiB
PHP

<?php
declare(strict_types=1);
require __DIR__ . '/lib.php';
$uuid = require_login();
$me = acct_get($uuid);
$my_calls = acct_all_calls($uuid); // primary + admin-added extra/club calls
$my_email = strtolower(trim($me['email'] ?? ''));
if (!$my_calls && $my_email === '') {
json_out(['ok' => true, 'nodes' => []]);
}
// Fetch reflector status via cURL
$ch = curl_init('http://127.0.0.1:8098/api/status');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_CONNECTTIMEOUT => 2,
]);
$json = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($json === false || $json === '') {
json_out(['ok' => false, 'error' => 'Cannot reach reflector API' . ($err ? ": $err" : '')], 502);
}
$data = json_decode($json, true);
if (!is_array($data) || !isset($data['nodes'])) {
json_out(['ok' => false, 'error' => 'Invalid reflector response'], 502);
}
$r = redis();
// Match nodes belonging to this user
$my_nodes = [];
foreach ($data['nodes'] as $node_call => $node_info) {
// Only LOCAL client nodes: skip remote trunk nodes (other reflectors'
// clients relayed over trunks) and bridge/gateway infrastructure.
if (!empty($node_info['remoteTrunk'])) continue;
if (stripos((string)($node_info['sw'] ?? ''), 'bridge') !== false) continue;
$sysop = strtoupper(trim($node_info['sysop'] ?? ''));
$match = false;
if ($my_calls && $sysop !== '' && in_array($sysop, $my_calls, true)) $match = true;
if (!$match && $my_calls && calls_match_node($my_calls, (string)$node_call)) $match = true;
// Also match if user is a node admin
if (!$match && $my_calls) {
$admins = $r->sMembers(rkey("node_admins:" . strtoupper($node_call)));
if (is_array($admins)) {
foreach ($my_calls as $c) {
if (in_array($c, $admins, true)) { $match = true; break; }
}
}
}
if ($match) {
// Add node admins info — sysop is always default admin
$stored_admins = $r->sMembers(rkey("node_admins:" . strtoupper($node_call)));
if (!is_array($stored_admins)) $stored_admins = [];
$all_admins = $stored_admins;
if ($sysop !== '' && !in_array($sysop, $all_admins, true)) {
array_unshift($all_admins, $sysop);
}
sort($all_admins);
$node_info['node_admins'] = $all_admins;
$my_nodes[$node_call] = $node_info;
}
}
json_out(['ok' => true, 'nodes' => $my_nodes]);