/* Settings form stays mounted while status polling updates only status elements. */
let networkBusy=false, networkState=null;
async function networkRequest(action,body={}){
const response=await fetch('/api/v1/network'+(action?'/'+action:''),{method:action?'POST':'GET',headers:action?{'Content-Type':'application/json','X-Athena-Deck':'1'}:{},body:action?JSON.stringify(body):undefined,signal:AbortSignal.timeout(40000)});
const value=await response.json();if(response.status===401){location.reload();throw Error('Bitte erneut anmelden.')}if(!response.ok)throw Error(value.error||'Netzwerkaktion fehlgeschlagen.');return value;
}
async function networkAction(action,body={}){
if(networkBusy)return;networkBusy=true;networkButtons();
const output=document.querySelector('#network-message');output.textContent='Wird ausgeführt …';
try{await networkRequest(action,body);output.textContent=action==='import'?'Konfiguration geprüft und geschützt auf Athena gespeichert.':action==='install'?'Installation läuft. Der Status aktualisiert sich automatisch.':'Einstellung übernommen.';}
catch(e){output.textContent=e.message;}
finally{networkBusy=false;await networkPage();}
}
function networkButtons(){
if(!networkState)return;
const s=networkState;
document.querySelectorAll('#network-page button').forEach(b=>b.disabled=networkBusy||s.state==='installing');
const set=(id,disabled)=>{const b=document.getElementById(id);if(b)b.disabled=b.disabled||disabled;};
set('network-install',s.installed||s.install_supported===false);
set('network-import',!s.installed||s.enabled||s.mode!=='lan'||!!s.pending);
set('network-connect',!s.configured||s.enabled);
set('network-disconnect',!s.enabled);
set('network-delete',!s.configured||s.enabled||s.mode!=='lan'||!!s.pending);
set('network-apply',!s.installed||!!s.pending);
const needed=s.pending?.target==='lan'?'lan':'tunnel';
set('network-confirm',!s.pending||s.ingress!==needed);
set('network-cancel',!s.pending);
}
async function networkPage(){
const view=document.querySelector('#view');
if(!document.querySelector('#network-page')){
view.innerHTML=`
EINSTELLUNGEN / NETZWERK
Dein Weg zu Athena.
Ein nativer WireGuard-Tunnel auf dem Debian-Server. Die Zugriffsmodi gelten für die freigegebenen Deck-Ports.
WireGuard-Modul
Wird geprüft …
Nativen Systemdienst einrichten
WireGuard läuft direkt auf Debian als systemd-Dienst, außerhalb von Docker. Die Einrichtung erfolgt mit deploy/setup_network_helper.py; dabei werden weder ein bestehender Gateway noch dessen Konfiguration automatisch übernommen.
Ein Peer mit IPv4 und optional IPv6 wird unterstützt. Schlüssel werden nicht angezeigt. Bei einer Migration darf derselbe Peer nicht gleichzeitig im alten Gateway aktiv sein. DNS bleibt unverändert; Shell-Hooks werden abgelehnt.
Aktivieren richtet den Tunnel ein. „Verbunden“ erscheint erst nach einem aktuellen Handshake.
Zugriff auf Deck und API
Öffne die angezeigte Zieladresse und bestätige dort innerhalb von 120 Sekunden. Ohne Bestätigung wird der vorige Modus wiederhergestellt.
Der SSH-Zugang bleibt als Verwaltungskanal erhalten. Die freigegebenen GUI-, API- und Web-Tool-Ports verwenden denselben Zugriffsmodus. Im Modus „Nur Tunnel“ gibt es bei Tunnelausfall keinen LAN-Fallback.
`;
document.querySelector('#network-import').onclick=async()=>{const input=document.querySelector('#network-file'),file=input.files[0];if(!file){document.querySelector('#network-message').textContent='Bitte zuerst eine .conf-Datei auswählen.';return}if(file.size>16384){document.querySelector('#network-message').textContent='Die Datei darf höchstens 16 KiB groß sein.';return}const config=await file.text();input.value='';await networkAction('import',{config});};
for(const action of ['connect','disconnect','delete','cancel'])document.querySelector('#network-'+action).onclick=()=>networkAction(action);
document.querySelector('#network-apply').onclick=()=>networkAction('mode',{mode:document.querySelector('#network-mode').value});
document.querySelector('#network-confirm').onclick=()=>networkAction('confirm',{trial_id:networkState?.pending?.id});
}
try{
const s=await networkRequest('');if(!document.querySelector('#network-page'))return;networkState=s;
const labels={'disabled-module':'Nicht angebunden',unavailable:'Nicht bereit',installing:'Installation läuft',disabled:'Deaktiviert',connecting:'Warte auf Handshake',connected:'Verbunden'};
document.querySelector('#network-state').textContent=labels[s.state]||'Nicht verfügbar';
const details=document.querySelector('#network-details');details.replaceChildren();
for(const [label,value] of [['Konfiguration',s.configured?'Gespeichert':'Keine'],['Letzter Handshake',s.latest_handshake?new Date(s.latest_handshake*1000).toLocaleString('de-DE'):'Noch keiner'],['Dieser Zugang',s.ingress==='management'?'SSH-Verwaltung':s.ingress==='tunnel'?'WireGuard-Tunnel':'LAN']]){const d=document.createElement('div'),small=document.createElement('small'),strong=document.createElement('strong');small.textContent=label;strong.textContent=value;d.append(small,strong);details.append(d);}
for(const [label,url] of [['LAN',s.lan_url],['Tunnel',s.tunnel_url]])if(url){const d=document.createElement('div'),a=document.createElement('a');a.href=url+'/#network';a.textContent=label+': '+url;a.target='_blank';a.rel='noopener';d.append(a);details.append(d);}
document.querySelector('#network-setup').hidden=!!s.installed;
document.querySelector('#network-config').hidden=false;
document.querySelector('#network-file').disabled=!s.installed||s.enabled||networkBusy;
document.querySelector('#network-access').hidden=false;
document.querySelector('#network-mode').disabled=!s.installed||!!s.pending||networkBusy;
document.querySelector('#network-notice').textContent=[s.error,s.job?.message,...(s.warnings||[])].filter(Boolean).join(' ');
document.querySelector('#network-current').textContent='Aktuell: '+({lan:'Nur lokales Netzwerk',tunnel:'Nur WireGuard-Tunnel',both:'Tunnel und LAN'}[s.mode]||'Noch nicht eingerichtet');
document.querySelector('#network-trial').hidden=!s.pending;
if(s.pending)document.querySelector('#network-countdown').textContent=`Test aktiv · ${s.pending.seconds_remaining} Sekunden bis zur automatischen Rücknahme. Bestätigung nötig über ${s.pending.target==='lan'?'LAN':'WireGuard'}.`;
networkButtons();
}catch(e){if(document.querySelector('#network-message'))document.querySelector('#network-message').textContent=e.message;}
}