Files
reflector-dashboard/auth/tgrequest.js
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

83 lines
3.8 KiB
JavaScript

'use strict';
// Request a TG — mirrors the DMR tgrequest flow. Submit -> pending -> an admin
// approves (in the admin TG editor) -> you become owner. One open request/user.
var $ = function (id) { return document.getElementById(id); };
function esc(s) { var d = document.createElement('div'); d.textContent = s == null ? '' : String(s); return d.innerHTML; }
function reqMsg(t, err) { var e = $('reqMsg'); if (!e) return; if (!t) { e.style.display = 'none'; return; } e.style.display = 'block'; e.textContent = t; e.style.color = err ? '#ff8080' : '#0f0'; }
async function reqApi(body) {
var r = await fetch('/auth/tglist_api.php', {
method: 'POST', credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': window._csrfToken || '' },
body: JSON.stringify(body)
});
return r.json().catch(function () { return null; });
}
function showPending(p) {
var box = $('reqPending'), form = $('reqForm'), cancel = $('reqCancel');
if (p) {
box.style.display = 'block';
box.innerHTML = 'You have a pending request for <b>TG ' + esc(p.tg) + '</b> ("' + esc(p.name) + '"). An admin will review it.';
// lock the form fields to the pending values
$('reqTg').value = p.tg; $('reqName').value = p.name || ''; $('reqSystem').value = p.system || '';
$('reqAllstar').value = p.allstar || ''; $('reqMode').value = p.mode || '';
Array.prototype.forEach.call(form.querySelectorAll('input'), function (i) { i.disabled = true; });
$('reqSubmit').disabled = true;
cancel.style.display = '';
} else {
box.style.display = 'none';
Array.prototype.forEach.call(form.querySelectorAll('input'), function (i) { i.disabled = false; });
$('reqSubmit').disabled = false;
cancel.style.display = 'none';
}
}
async function loadPending() {
var j = await reqApi({ action: 'my_request' });
if (j && j.ok) showPending(j.pending || null);
}
var ERRS = {
no_callsign: 'Your account has no callsign — set one in your profile first.',
invalid_tg: 'Enter a valid TG number.',
tg_already_taken: 'That TG already exists.',
pending_request_exists: 'You already have a pending request.',
name_required: 'Name is required.',
invalid_allstar: 'AllStar node must be digits only.'
};
document.addEventListener('DOMContentLoaded', function () {
fetch('/auth/me.php', { credentials: 'same-origin' })
.then(function (r) { return r.json(); })
.then(function (j) {
if (j && j.csrf_token) window._csrfToken = j.csrf_token;
var cs = (j && j.callsign) ? String(j.callsign).toUpperCase() : '';
var el = $('reqCallsign');
if (el) el.innerHTML = cs ? esc(cs) : '<span style="color:#ff8080;">No callsign on your account — set one in your profile first.</span>';
})
.catch(function () {})
.finally(loadPending);
$('reqForm').addEventListener('submit', async function (e) {
e.preventDefault();
var tg = parseInt($('reqTg').value, 10);
if (!tg || tg <= 0) { reqMsg('Enter a valid TG number', true); return; }
if (!($('reqName').value || '').trim()) { reqMsg('Name is required', true); return; }
var res = await reqApi({
action: 'request', tg: tg,
name: $('reqName').value, system: $('reqSystem').value,
allstar: ($('reqAllstar').value || '').trim(), mode: $('reqMode').value
});
if (res && res.ok) { reqMsg('Request submitted — awaiting admin approval.', false); await loadPending(); }
else reqMsg(ERRS[res && res.error] || (res && res.error) || 'Failed', true);
});
$('reqCancel').addEventListener('click', async function () {
if (!confirm('Cancel your pending TG request?')) return;
var res = await reqApi({ action: 'request_cancel' });
if (res && res.ok) { reqMsg('Request cancelled.', false); await loadPending(); }
else reqMsg((res && res.error) || 'Failed', true);
});
});