package master const masterHTML = ` SessionGuard Master
SessionGuard
Master Console
Server
Online
Aktive Sitzungen
Cleanup geplant

Terminalserver

Server auswählen

Links einen Agent auswählen.
` const masterJS = ` let selected=null, current=null; const $=id=>document.getElementById(id); function esc(s){return String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));} function bytes(n){if(!n)return '–';let u=['B','KB','MB','GB','TB'],i=0;while(n>=1024&&i1?1:0)+' '+u[i]} function age(sec){if(!sec)return '–';let d=Math.floor(sec/86400),h=Math.floor(sec%86400/3600),m=Math.floor(sec%3600/60);return d+'d '+h+'h '+m+'m'} function toast(t){let e=$('toast');e.textContent=t;e.style.display='block';setTimeout(()=>e.style.display='none',2500)} async function api(url,opt){let r=await fetch(url,opt);if(r.status===401){location='/login';return}let j=await r.json().catch(()=>({}));if(!r.ok)throw new Error(j.error||r.statusText);return j} async function refresh(){try{let d=await api('/api/v1/dashboard');let a=d.agents||[];$('mServers').textContent=a.length;$('mOnline').textContent=a.filter(x=>x.online).length;$('mActive').textContent=a.reduce((n,x)=>n+x.active_sessions,0);$('mCleanup').textContent=a.reduce((n,x)=>n+(x.snapshot.pending_cleanup||[]).length,0);$('agents').innerHTML=''+a.map(x=>'').join('')+'
StatusServerSitzungenBuild
'+(x.online?'Online':'Offline')+''+esc(x.name)+'
'+esc(x.snapshot.server.os||'')+'
'+x.active_sessions+' aktiv / '+x.total_sessions+''+esc(x.snapshot.agent_version||'–')+'
';document.querySelectorAll('.row').forEach(r=>r.onclick=()=>selectAgent(r.dataset.id));if(selected)selectAgent(selected,true)}catch(e){toast(e.message)}} async function selectAgent(id,quiet){selected=id;try{current=await api('/api/v1/agents/'+encodeURIComponent(id));renderDetail(current)}catch(e){if(!quiet)toast(e.message)}} function renderDetail(a){let s=a.snapshot.server||{},sessions=a.snapshot.sessions||[],p=a.desired_policy||defaultPolicy(a.snapshot.policy_revision);$('detailTitle').textContent=a.name||a.id;$('detail').className='';$('detail').innerHTML='
Uptime
'+age(s.uptime_seconds)+'
RAM frei
'+bytes(s.memory_available)+' / '+bytes(s.memory_total)+'
Policy
'+esc(a.snapshot.policy_revision||'–')+'
'+sessions.map(x=>'').join('')+'
IDBenutzerStatusClient
'+x.id+''+esc((x.domain?x.domain+'\\':'')+x.user)+''+esc(x.state)+''+esc(x.client_name||'–')+'
'+policyForm(p)} function defaultPolicy(rev){return {revision:rev||'',cleanup:{enabled:true,grace_seconds:600,poll_seconds:10,retry_seconds:60,dry_run:true,exclude_users:['Administrator','DefaultAccount','WDAGUtilityAccount'],exclude_sids:['S-1-5-18','S-1-5-19','S-1-5-20'],allowed_profile_roots:['C:\\Users']},templates:[]}} function policyForm(p){let c=p.cleanup||{};return '
Policy bearbeiten
'} function lines(id){return $(id).value.split('\n').map(x=>x.trim()).filter(Boolean)} async function savePolicy(all){if(!selected)return;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(all?'/api/v1/policy/all':'/api/v1/agents/'+encodeURIComponent(selected)+'/policy',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(p)});toast(all?'Policy auf alle Server angewendet':'Policy gespeichert');await selectAgent(selected,true)}catch(e){toast(e.message)}} refresh();setInterval(refresh,5000);`