// SvxPortal — 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. // auth_ui.js — shared sign-in / register / sign-out transport (dmr-web, svx-web). // Canonical copy: /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; })();