Files
reflector-dashboard/lib/auth_ui.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

54 lines
2.7 KiB
JavaScript

// auth_ui.js — shared sign-in / register / sign-out transport (dmr-web, svx-web).
// Canonical copy: callmgr2/www-mumien/lib/auth_ui.js; other repos carry a COPY.
// Needs lib/api.js. Pages keep their own field validation and messages; this
// owns the request/response contract so both webs behave the same.
//
// authLogin({ endpoint, body, csrf, onFail(j, r) }) → true on {ok:true}
// authRegister({ endpoint, csrf, msg(text, isErr) }) reads the reg* form fields
// authLogout({ endpoint, method, after })
(function () {
'use strict';
const REG_IDS = ['regCallsign', 'regFirstname', 'regLastname', 'regEmail', 'regPass1', 'regPass2', 'regCity', 'regState', 'regCountry'];
async function authLogin(o) {
const r = await apiFetch(o.endpoint, { body: o.body, csrf: o.csrf || window._csrfToken || '' });
if (!r.ok || !r.json || !r.json.ok) {
if (typeof o.onFail === 'function') o.onFail(r.json, r);
return false;
}
return true;
}
async function authRegister(o) {
const g = id => document.getElementById(id);
const v = id => (g(id) ? g(id).value : '').trim();
const msg = typeof o.msg === 'function' ? o.msg : function () {};
msg(null);
const callsign = v('regCallsign').toUpperCase(), firstname = v('regFirstname'), lastname = v('regLastname'),
email = v('regEmail'), pass1 = g('regPass1') ? g('regPass1').value : '', pass2 = g('regPass2') ? g('regPass2').value : '',
city = v('regCity'), state = v('regState'), country = v('regCountry');
if (!callsign || !firstname || !email || !pass1) { msg('Fill in all required fields.', true); return false; }
if (pass1 !== pass2) { msg('Passwords do not match.', true); return false; }
if (pass1.length < 6) { msg('Password must be at least 6 characters.', true); return false; }
const j = await apiJson(o.endpoint, { callsign, firstname, lastname, email, password: pass1, password2: pass2, city, state, country },
{ csrf: o.csrf || window._csrfToken || '' });
if (j && j.ok) {
const emailNote = j.email_sent ? ' A verification email has been sent.' : '';
msg('Account created!' + emailNote + ' An administrator will activate your account after email verification.', false);
REG_IDS.forEach(id => { if (g(id)) g(id).value = ''; });
return true;
}
msg((j && j.error) || 'Registration failed.', true);
return false;
}
async function authLogout(o) {
try { await apiFetch(o.endpoint, { method: o.method || 'GET' }); } catch (_) {}
if (typeof o.after === 'function') o.after();
}
window.authLogin = authLogin;
window.authRegister = authRegister;
window.authLogout = authLogout;
})();