Files
sessiongurad/internal/agent/ui.go
jbergner 1d8e36c53a
Some checks failed
release-tag / release-image (push) Has been cancelled
Init
2026-08-22 08:10:11 +02:00

11 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package agent
const agentHTML = `<!doctype html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>SessionGuard Agent</title><style>
:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;color-scheme:dark;background:#0c1120;color:#edf2fb}*{box-sizing:border-box}body{margin:0;background:#0c1120}.wrap{max-width:1200px;margin:auto;padding:28px}.top{display:flex;justify-content:space-between;align-items:center}.brand{font-size:20px;font-weight:750}.muted{color:#95a3be}.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:20px 0}.card,.panel{background:#131d32;border:1px solid #263653;border-radius:16px}.card{padding:16px}.value{font-size:24px;font-weight:750;margin-top:7px}.panel{margin-top:15px;overflow:hidden}.panel h2{font-size:15px;padding:14px 16px;margin:0;border-bottom:1px solid #263653}.table{width:100%;border-collapse:collapse}.table td,.table th{padding:11px 13px;border-bottom:1px solid #22314d;text-align:left;font-size:13px}.table th{color:#93a5c2}.form{padding:16px;display:grid;gap:11px}.cols{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}input,textarea{width:100%;background:#0d1629;color:#edf2fb;border:1px solid #334866;border-radius:9px;padding:8px}textarea{min-height:110px;font-family:ui-monospace,Consolas,monospace;font-size:12px}.check{display:flex;gap:8px;align-items:center}.check input{width:auto}button{background:#5d8eff;color:#fff;border:0;border-radius:9px;padding:9px 13px;font-weight:650;cursor:pointer}.secondary{background:#22314d}.bad{color:#ff9b9b}.good{color:#74e59a}@media(max-width:850px){.grid{grid-template-columns:repeat(2,1fr)}.cols{grid-template-columns:1fr}}</style></head><body><div class="wrap"><div class="top"><div><div class="brand">SessionGuard Agent</div><div class="muted" id="host">Lokaler Terminalserver</div></div><form action="/logout" method="post"><button class="secondary">Abmelden</button></form></div><div class="grid"><div class="card"><div class="muted">Aktiv</div><div class="value" id="active"></div></div><div class="card"><div class="muted">Sitzungen</div><div class="value" id="total"></div></div><div class="card"><div class="muted">Cleanup geplant</div><div class="value" id="pending"></div></div><div class="card"><div class="muted">Master</div><div class="value" style="font-size:16px" id="master"></div></div></div><section class="panel"><h2>Sitzungen</h2><div id="sessions"></div></section><section class="panel"><h2>Lokale Policy</h2><div id="policy"></div></section></div><script src="/app.js"></script></body></html>`
const agentJS = `
const $=id=>document.getElementById(id);function esc(s){return String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}async function api(u,o){let r=await fetch(u,o),j=await r.json().catch(()=>({}));if(!r.ok)throw new Error(j.error||r.statusText);return j}function lines(id){return $(id).value.split('\n').map(x=>x.trim()).filter(Boolean)}
async function refresh(){try{let d=await api('/api/v1/status'),s=d.snapshot||{},ss=s.sessions||[];$('host').textContent=(s.server&&s.server.hostname)||'Lokaler Terminalserver';$('active').textContent=ss.filter(x=>x.state==='Active').length;$('total').textContent=ss.length;$('pending').textContent=(s.pending_cleanup||[]).length;$('master').innerHTML=d.master_error?'<span class="bad">Offline</span>':'<span class="good">Verbunden</span>';$('sessions').innerHTML='<table class="table"><thead><tr><th>ID</th><th>Benutzer</th><th>Status</th><th>Client</th></tr></thead><tbody>'+ss.map(x=>'<tr><td>'+x.id+'</td><td>'+esc((x.domain?x.domain+'\\':'')+x.user)+'</td><td>'+esc(x.state)+'</td><td>'+esc(x.client_name||'')+'</td></tr>').join('')+'</tbody></table>'}catch(e){$('master').innerHTML='<span class="bad">'+esc(e.message)+'</span>'}}
async function loadPolicy(){try{let p=await api('/api/v1/policy'),c=p.cleanup||{};$('policy').innerHTML='<div class="form"><div class="cols"><label>Grace (s)<input id="grace" type="number" value="'+(c.grace_seconds||600)+'"></label><label>Polling (s)<input id="poll" type="number" value="'+(c.poll_seconds||10)+'"></label><label>Retry (s)<input id="retry" type="number" value="'+(c.retry_seconds||60)+'"></label></div><div class="check"><input id="enabled" type="checkbox" '+(c.enabled?'checked':'')+'> Cleanup aktiv</div><div class="check"><input id="dry" type="checkbox" '+(c.dry_run?'checked':'')+'> Dry-Run</div><label>Benutzer ausschließen<textarea id="users">'+esc((c.exclude_users||[]).join('\n'))+'</textarea></label><label>SIDs ausschließen<textarea id="sids">'+esc((c.exclude_sids||[]).join('\n'))+'</textarea></label><label>Profil-Roots<textarea id="roots">'+esc((c.allowed_profile_roots||[]).join('\n'))+'</textarea></label><label>Templates (JSON Array)<textarea id="templates" style="min-height:220px">'+esc(JSON.stringify(p.templates||[],null,2))+'</textarea></label><div><button onclick="savePolicy()">Lokal speichern</button></div><div class="muted">Wenn der Master für diesen Agent eine gewünschte Policy gesetzt hat, ist diese nach Wiederherstellung der Verbindung wieder maßgeblich.</div></div>'}catch(e){$('policy').textContent=e.message}}
async function savePolicy(){try{let p={cleanup:{enabled:$('enabled').checked,grace_seconds:+$('grace').value,poll_seconds:+$('poll').value,retry_seconds:+$('retry').value,dry_run:$('dry').checked,exclude_users:lines('users'),exclude_sids:lines('sids'),allowed_profile_roots:lines('roots')},templates:JSON.parse($('templates').value||'[]')};await api('/api/v1/policy',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(p)});await loadPolicy()}catch(e){alert(e.message)}}refresh();loadPolicy();setInterval(refresh,5000);`