MCPcopy Create free account
hub / github.com/PierreGode/Ragnar / loadSecurityConfig

Function loadSecurityConfig

web/scripts/ragnar_modern.js:5523–5657  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

5521 if (ve) {
5522 let veHtml;
5523 if (ve.via_vpn) {
5524 const via = escapeHtml(String(ve.interface || 'tunnel'))
5525 + (ve.kind ? ' · ' + escapeHtml(ve.kind) : '')
5526 + (ve.endpoint ? ' → ' + escapeHtml(ve.endpoint) : '');
5527 veHtml = '<span class="text-amber-300">yes</span> <span class="text-gray-500">(via ' + via + ')</span>';
5528 } else {
5529 veHtml = '<span id="vpn-egress-result" class="text-gray-500">no local tunnel</span> '
5530 + '<select id="vpn-egress-iface" class="bg-slate-800 border border-slate-700 rounded text-xs text-gray-300 px-1 py-0.5 mx-1">'
5531 + '<option value="">auto (default route)</option></select>'
5532 + '<button onclick="checkVpnEgress()" class="text-xs text-cyan-400 hover:text-cyan-300 underline">check egress (catches VPN/Tor on the router)</button>';
5533 }
5534 row('Traffic via VPN', veHtml);
5535 }
5536
5537 const scopeNote = d.interface
5538 ? `<p class="text-[11px] text-cyan-400/80 mt-2">Scoped to <span class="font-mono">${escapeHtml(d.interface)}</span> — gateway + nameservers are what this interface's own network provides.</p>` : '';
5539 const src = (d.sources && d.sources.length)
5540 ? `<p class="text-[11px] text-gray-500 mt-2">Sources: ${d.sources.map(escapeHtml).join(', ')}</p>` : '';
5541 out.innerHTML = `<table class="min-w-full text-sm">
5542 <tbody>${rows.join('')}</tbody></table>${scopeNote}${src}`;
5543 // Fill the egress-check interface selector (auto + each real NIC) so
5544 // the LAN path can be tested even when WiFi carries the default route.
5545 const sel = document.getElementById('vpn-egress-iface');
5546 if (sel) {
5547 fetchAPI('/api/net/interfaces').then(x => {
5548 (x.interfaces || []).forEach(i => {
5549 const o = document.createElement('option');
5550 o.value = i.name;
5551 o.textContent = i.name + (i.type && i.type !== 'ethernet' ? ' (' + i.type + ')' : '');
5552 sel.appendChild(o);
5553 });
5554 // A scoped identity view should test the same interface's egress.
5555 if (d.interface) sel.value = d.interface;
5556 }).catch(() => {});
5557 }
5558 } catch (e) {
5559 out.innerHTML = '<p class="text-red-400">Failed: ' + escapeHtml(e.message) + '</p>';
5560 }
5561}
5562
5563async function checkVpnEgress() {
5564 const cell = document.getElementById('vpn-egress-result');
5565 if (!cell) return;
5566 const sel = document.getElementById('vpn-egress-iface');
5567 const iface = sel && sel.value ? sel.value : '';
5568 const label = iface ? 'via ' + escapeHtml(iface) : 'default route';
5569 cell.innerHTML = '<span class="text-gray-400">checking egress ' + label + '… (public IP, known-VPN IP list, Tor exit)</span>';
5570 try {
5571 const d = await fetchAPI('/api/net/vpn-check' + (iface ? '?interface=' + encodeURIComponent(iface) : ''));
5572 const ifNote = d.interface ? ' <span class="text-gray-500">[' + escapeHtml(d.interface) + ']</span>' : '';
5573 const why = (d.reasons && d.reasons.length)
5574 ? ' <span class="text-gray-500">(' + d.reasons.map(escapeHtml).join('; ') + ')</span>' : '';
5575 if (d.verdict === 'vpn') {
5576 cell.innerHTML = '<span class="text-amber-300">yes</span>' + ifNote + why;
5577 } else if (d.verdict === 'likely') {
5578 cell.innerHTML = '<span class="text-amber-300">likely</span>' + ifNote + why;
5579 } else if (d.verdict === 'no') {
5580 const via = [d.isp, d.public_ip].filter(Boolean).map(escapeHtml).join(' · ');

Callers 1

loadConfigDataFunction · 0.70

Calls 3

addMethod · 0.80
errorMethod · 0.80
fetchAPIFunction · 0.70

Tested by

no test coverage detected