/* ========================= DNS CACHE (mit TTL) ========================= */ const dnsCache = {} async function getDNS(domain){ const now = Date.now() const TTL = 30000 // 30 Sekunden if(dnsCache[domain] && (now - dnsCache[domain].time < TTL)){ return dnsCache[domain].ips } try{ const res = await api(API + "/dns/" + domain) const ips = res.ips || [] dnsCache[domain] = { ips: ips, time: now } return ips }catch(e){ dnsCache[domain] = { ips: [], time: now } return [] } } /* ========================= DOMAINS + SUBDOMAINS ========================= */ window.loadDomains = async function(){ const domains = await api(API + "/domains") const subs = await api(API + "/subdomains") const table = document.getElementById("domains") table.innerHTML = "" for(const d of domains){ const tr = document.createElement("tr") // Subdomains Liste const sublist = subs .filter(s => s.domain_id === d.id) .map(s => `
↳ ${s.subdomain}.${s.domain_name} ...
`).join("") tr.innerHTML = ` ${d.domain_name} ${sublist} ${d.provider || ""} ${d.ip_address || ""} ${d.resource_name || ""} ... ${d.yearly_cost || ""} ` table.appendChild(tr) /* ========================= SERVER ZUORDNUNG SUBS ========================= */ const resources = window.resources || [] subs.forEach(s => { const server = resources.find(r => Array.isArray(r.ips) && r.ips.some(ip => ip.ip === s.ip_address) ) if(server){ const el = document.getElementById("subserver-"+s.id) if(el){ el.innerText = " → " + server.name } } }) /* ========================= DNS CHECK DOMAIN ========================= */ try{ const ips = await getDNS(d.domain_name) let status = "❌" if(ips.length){ if(d.ip_address && ips.includes(d.ip_address)){ status = "✅ " + ips.join(", ") }else{ status = "⚠ " + ips.join(", ") } } document.getElementById("dns-"+d.id).innerHTML = status }catch(e){ document.getElementById("dns-"+d.id).innerHTML = "❌" } /* ========================= DNS CHECK SUBDOMAINS ========================= */ subs .filter(s => s.domain_id === d.id) .forEach(async s => { const full = s.subdomain + "." + s.domain_name try{ const ips = await getDNS(full) let status = "❌" if(ips.length){ if(s.ip_address && ips.includes(s.ip_address)){ status = "✅ " + ips.join(", ") }else{ status = "⚠ " + ips.join(", ") } } document.getElementById("subdns-"+s.id).innerHTML = status }catch(e){ document.getElementById("subdns-"+s.id).innerHTML = "❌" } }) } } /* ========================= DOMAIN CRUD ========================= */ window.saveDomain = async function(){ const id = document.getElementById("domain_id").value let cost = document.getElementById("domain_cost").value if(cost) cost = cost.replace(",", ".") const data = { domain_name: domain_name.value, provider: domain_provider.value, ip_address: domain_ip.value, yearly_cost: cost || null, notes: domain_notes.value } if(id){ await api(API+"/domains/"+id,{ method:"PUT", headers:{'Content-Type':'application/json'}, body:JSON.stringify(data) }) }else{ await api(API+"/domains",{ method:"POST", headers:{'Content-Type':'application/json'}, body:JSON.stringify(data) }) } closeDomainModal() loadDomains() loadMapping() loadCosts() } window.deleteDomain = async function(id){ if(!confirm("Domain löschen?")) return await api(API + "/domains/" + id, { method: "DELETE" }) loadDomains() } window.moveDomain = async function(id, direction){ try{ await api(API + "/domains/" + id + "/move", { method: "POST", headers: {'Content-Type':'application/json'}, body: JSON.stringify({ direction }) }) loadDomains() loadMapping() }catch(e){ console.log(e) } } /* ========================= SUBDOMAIN CRUD ========================= */ window.saveSubdomain = async function(){ const id = document.getElementById("sub_id").value const domain_id = document.getElementById("sub_domain_id").value const subdomain = document.getElementById("sub_name").value const ip_address = document.getElementById("sub_ip").value const data = { domain_id, subdomain, ip_address } if(id){ await api(API+"/subdomains/"+id,{ method:"PUT", headers:{'Content-Type':'application/json'}, body:JSON.stringify(data) }) }else{ await api(API+"/subdomains",{ method:"POST", headers:{'Content-Type':'application/json'}, body:JSON.stringify(data) }) } closeSubModal() loadDomains() } window.deleteSub = async function(id){ if(!confirm("Subdomain löschen?")) return await api(API + "/subdomains/" + id, { method: "DELETE" }) loadDomains() } /* ========================= DOMAIN MAPPING ========================= */ window.loadMapping = async function(){ const data = await api(API + "/domainmap") const table = document.getElementById("mapping") table.innerHTML = "" data.forEach(m => { const tr = document.createElement("tr") tr.innerHTML = ` ${m.domain_name} ${m.ip_address} ${m.server_name || ""} ` table.appendChild(tr) }) }