7013a5fd2e
Leg A: „Hálózat" card on Beállítások → Rendszer — Helyi cím (LAN), Hálózati név (only while Megosztás is enabled), Átjáró; live per render, stored nowhere (S-5), „—" on unavailable. Leg B: network section in the Debug system dump (interfaces/route/DNS/ lan_address), best-effort per item via the samba-netns door. Leg C: NetBIOS trap named — Szerver field helper text + a purely lexical hint on unreachable failures for single-label non-IP names. Design note: all guest-net reads go through docker exec into the host-networked felhom-samba container (stacks/guestnet.go, one seam) — the controller's own netns is the docker bridge, so /proc/net/route etc. would answer 172.x (the S-2 trap). Red-proofs: A2 gate-drop and C2 lexical-invert both failed as required. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UuFPHmHNrCJj1VhY6QdDMU
423 lines
20 KiB
HTML
423 lines
20 KiB
HTML
{{define "settings_system"}}
|
||
{{template "layout_start" .}}
|
||
|
||
<div class="page-header">
|
||
<h2>Beállítások — Rendszer</h2>
|
||
</div>
|
||
|
||
<!-- Section A: System Configuration (read-only) -->
|
||
<div class="settings-card">
|
||
<h3>Rendszer konfiguráció</h3>
|
||
<p class="settings-card-desc">Az üzemeltető által beállított értékek. Módosításhoz kérd az üzemeltetőt.</p>
|
||
<div class="settings-grid">
|
||
<div class="settings-row">
|
||
<span class="settings-label">Ügyfél azonosító</span>
|
||
<span class="settings-value mono">{{.CustomerID}}</span>
|
||
</div>
|
||
<div class="settings-row">
|
||
<span class="settings-label">Ügyfél neve</span>
|
||
<span class="settings-value">{{.CustomerName}}</span>
|
||
</div>
|
||
<div class="settings-row">
|
||
<span class="settings-label">Domain</span>
|
||
<span class="settings-value mono">{{.CustomerDomain}}</span>
|
||
</div>
|
||
{{if .GitRepoURL}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Alkalmazás sablon forrás</span>
|
||
<span class="settings-value mono settings-value-truncate">{{.GitRepoURL}}</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Sablon szinkronizálás</span>
|
||
<span class="settings-value mono">{{.GitSyncInterval}}</span>
|
||
</div>
|
||
<div class="settings-row">
|
||
<span class="settings-label">Biztonsági mentés</span>
|
||
<span class="settings-value">{{if .BackupEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span>{{else}}<span class="state-text-neutral">Inaktív</span>{{end}}</span>
|
||
</div>
|
||
{{if .BackupEnabled}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Mentés ütemezés</span>
|
||
<span class="settings-value mono">{{.DBDumpSchedule}} / {{.ResticSchedule}}</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Monitoring</span>
|
||
<span class="settings-value">{{if .MonitoringEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span>{{else}}<span class="state-text-neutral">Inaktív</span>{{end}}</span>
|
||
</div>
|
||
{{if .MonitoringEnabled}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Healthchecks URL</span>
|
||
<span class="settings-value mono settings-value-truncate">{{if .HealthchecksBase}}{{.HealthchecksBase}}{{else}}–{{end}}</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Hub jelentés</span>
|
||
<span class="settings-value">{{if .HubEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span>{{else}}–{{end}}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Section: Version & Update -->
|
||
<div class="settings-card">
|
||
<h3>Verzió és frissítés</h3>
|
||
<div class="settings-grid">
|
||
<div class="settings-row">
|
||
<span class="settings-label">Jelenlegi verzió</span>
|
||
<span class="settings-value mono">{{.Version}}</span>
|
||
</div>
|
||
{{if .SelfUpdateEnabled}}
|
||
{{if .LatestVersion}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Legújabb verzió</span>
|
||
<span class="settings-value mono">
|
||
{{.LatestVersion}}
|
||
{{if .UpdateAvailable}}
|
||
<span class="state-text-run" style="margin-left:0.5em;">● Frissítés elérhető</span>
|
||
{{else}}
|
||
<span style="margin-left:0.5em; color:var(--text-3);">— naprakész</span>
|
||
{{end}}
|
||
</span>
|
||
</div>
|
||
{{end}}
|
||
{{if .LastCheckTime}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Utolsó ellenőrzés</span>
|
||
<span class="settings-value mono">{{.LastCheckTime}}</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Registry</span>
|
||
<span class="settings-value">{{if .RegistryAnonymous}}nyilvános (hitelesítés nélkül){{else}}hitelesített{{end}}</span>
|
||
</div>
|
||
{{if .LastCheckError}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Hiba</span>
|
||
<span class="settings-value state-text-crit">{{.LastCheckError}}</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Automatikus frissítés</span>
|
||
<span class="settings-value">
|
||
{{if .AutoUpdateEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span> <span class="mono">({{.AutoUpdateTime}})</span>{{else}}–{{end}}
|
||
</span>
|
||
</div>
|
||
{{if .ControllerFloor}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Minimális verzió (üzemeltető)</span>
|
||
<span class="settings-value mono">
|
||
{{.ControllerFloor}}
|
||
<span style="margin-left:0.5em; color:#888;">— a rendszer automatikusan erre a verzióra frissít, ha régebbi</span>
|
||
</span>
|
||
</div>
|
||
{{end}}
|
||
{{if .UpdateRunning}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Állapot</span>
|
||
<span class="settings-value state-text-progress" id="auto-update-status"><svg class="ico ico-sm ico-spin"><use href="#i-rotate-cw"/></svg> Frissítés folyamatban — a vezérlő hamarosan újraindul…</span>
|
||
</div>
|
||
{{end}}
|
||
{{with .LastUpdateState}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Utolsó frissítés</span>
|
||
<span class="settings-value">
|
||
{{if eq .Status "success"}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Sikeres</span> ({{.PreviousVersion}} → {{.TargetVersion}})
|
||
{{else if eq .Status "failed"}}<span class="state-text-crit"><svg class="ico ico-sm"><use href="#i-x"/></svg> Sikertelen</span> — {{.Error}}
|
||
{{else if eq .Status "pending"}}<span class="state-text-progress"><svg class="ico ico-sm ico-spin"><use href="#i-rotate-cw"/></svg> Folyamatban</span>
|
||
{{end}}
|
||
</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row" style="padding-top: 0.5em;">
|
||
<span class="settings-label"></span>
|
||
<span class="settings-value">
|
||
<button class="btn btn-secondary btn-sm" id="btn-check-update" onclick="checkUpdate()">Frissítés keresése</button>
|
||
{{if .UpdateAvailable}}
|
||
<button class="btn btn-primary btn-sm" id="btn-trigger-update" onclick="triggerUpdate()" style="margin-left:0.5em;">Frissítés telepítése</button>
|
||
{{end}}
|
||
<span id="update-status-msg" style="margin-left:0.5em; display:none;"></span>
|
||
</span>
|
||
</div>
|
||
{{end}}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Section: Network (R-66) — the box's own address. Every value is live-computed per render and
|
||
stored NOWHERE (S-5: a DHCP lease persisted anywhere eventually misdirects people); a missing
|
||
value renders „—" because an address-less row beats a wrong address. -->
|
||
<div class="settings-card">
|
||
<h3>Hálózat</h3>
|
||
<div class="settings-grid">
|
||
<div class="settings-row">
|
||
<span class="settings-label">Helyi cím (LAN)</span>
|
||
<span class="settings-value mono">{{if .NetLANAddress}}{{.NetLANAddress}}{{else}}— <span style="color:var(--text-3);">nem állapítható meg</span>{{end}}</span>
|
||
</div>
|
||
{{if .NetSMBName}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Hálózati név</span>
|
||
<span class="settings-value mono">\\{{.NetSMBName}}</span>
|
||
</div>
|
||
{{end}}
|
||
<div class="settings-row">
|
||
<span class="settings-label">Átjáró</span>
|
||
<span class="settings-value mono">{{if .NetGateway}}{{.NetGateway}}{{else}}— <span style="color:var(--text-3);">nem állapítható meg</span>{{end}}</span>
|
||
</div>
|
||
</div>
|
||
<p class="settings-card-desc" style="margin-top:0.5em;">Ezek az értékek a helyi hálózattól függenek és változhatnak. Távoli hibaelhárításnál ezt az oldalt kérjük felolvasni.</p>
|
||
</div>
|
||
|
||
<div class="settings-card">
|
||
<h3>Szerver memória (RAM)</h3>
|
||
{{if .MemorySupported}}
|
||
{{if .MemoryReachable}}
|
||
<div class="settings-grid">
|
||
<div class="settings-row">
|
||
<span class="settings-label">Jelenlegi memória</span>
|
||
<span class="settings-value mono">{{.MemoryAllocatedMB}} MB</span>
|
||
</div>
|
||
<div class="settings-row">
|
||
<span class="settings-label">Felhasznált</span>
|
||
<span class="settings-value mono">{{.MemoryUsageMB}} MB</span>
|
||
</div>
|
||
<div class="settings-row">
|
||
<span class="settings-label">Megengedett tartomány</span>
|
||
<span class="settings-value mono">{{.MemoryMinMB}} MB – {{.MemoryMaxMB}} MB</span>
|
||
</div>
|
||
<div class="settings-row" style="padding-top: 0.5em;">
|
||
<span class="settings-label">Új méret (MB)</span>
|
||
<span class="settings-value">
|
||
<input type="number" id="mem-input" class="input mono" style="width:8em;"
|
||
value="{{.MemoryAllocatedMB}}" min="{{.MemoryMinMB}}" max="{{.MemoryMaxMB}}" step="256"
|
||
data-current="{{.MemoryAllocatedMB}}">
|
||
<button class="btn btn-primary btn-sm" id="btn-mem-resize" onclick="resizeMemory()" style="margin-left:0.5em;">Átméretezés</button>
|
||
<span id="mem-status-msg" style="margin-left:0.5em; display:none;"></span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
{{else}}
|
||
<div class="settings-grid">
|
||
<div class="settings-row">
|
||
<span class="settings-label">Jelenlegi memória</span>
|
||
<span class="settings-value mono">{{if .MemoryProcMB}}{{.MemoryProcMB}} MB{{else}}n/a{{end}}</span>
|
||
</div>
|
||
</div>
|
||
<p class="settings-card-desc">A kiszolgáló ügynök jelenleg nem elérhető — próbáld meg később.</p>
|
||
{{end}}
|
||
{{else}}
|
||
<p class="settings-card-desc">A memória átméretezéséhez a kiszolgáló rendszerfrissítése szükséges.</p>
|
||
{{end}}
|
||
</div>
|
||
|
||
<div id="dialog-root"></div>
|
||
<script>
|
||
// Light overlay dialog (D1) — replaces the native blocking browser dialogs (same texts).
|
||
function escText(s){var d=document.createElement('div');d.textContent=String(s==null?'':s);return d.innerHTML;}
|
||
function closeDialog(){ var r=document.getElementById('dialog-root'); if(r) r.innerHTML=''; }
|
||
function openDialog(opts){
|
||
var root=document.getElementById('dialog-root');
|
||
if(!root) return;
|
||
root.innerHTML='<div class="confirm-overlay" onclick="if(event.target===this)document.getElementById(\'dialog-cancel\').click()"><div class="confirm-box">'
|
||
+'<h3>'+escText(opts.title||'Megerősítés')+'</h3>'
|
||
+'<p style="white-space:pre-line">'+escText(opts.message||'')+'</p>'
|
||
+'<div class="form-actions"><button id="dialog-go" class="btn btn-primary">'+escText(opts.confirmLabel||'Megerősítés')+'</button>'
|
||
+'<button type="button" class="btn btn-outline" id="dialog-cancel">Mégsem</button></div>'
|
||
+'</div></div>';
|
||
document.getElementById('dialog-go').onclick=function(){ closeDialog(); if(opts.onConfirm) opts.onConfirm(); };
|
||
document.getElementById('dialog-cancel').onclick=function(){ closeDialog(); if(opts.onCancel) opts.onCancel(); };
|
||
}
|
||
|
||
function checkUpdate() {
|
||
var btn = document.getElementById('btn-check-update');
|
||
var msg = document.getElementById('update-status-msg');
|
||
btn.disabled = true;
|
||
btn.textContent = 'Ellenőrzés...';
|
||
msg.style.display = 'none';
|
||
fetch('/api/selfupdate/check', {method:'POST', headers: csrfHeaders()})
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
if (data.ok) {
|
||
location.reload();
|
||
} else {
|
||
msg.textContent = data.error || 'Hiba történt';
|
||
msg.style.display = 'inline';
|
||
btn.disabled = false;
|
||
btn.textContent = 'Frissítés keresése';
|
||
}
|
||
})
|
||
.catch(function() {
|
||
msg.textContent = 'Kapcsolódási hiba';
|
||
msg.style.display = 'inline';
|
||
btn.disabled = false;
|
||
btn.textContent = 'Frissítés keresése';
|
||
});
|
||
}
|
||
|
||
function triggerUpdate() {
|
||
openDialog({title:'Vezérlő frissítése', confirmLabel:'Frissítés',
|
||
message:'Biztosan frissíti a controllert?\n\nA folyamat alatt a vezérlőpult rövid időre elérhetetlenné válik.',
|
||
onConfirm:doTriggerUpdate});
|
||
}
|
||
function doTriggerUpdate() {
|
||
var btn = document.getElementById('btn-trigger-update');
|
||
var checkBtn = document.getElementById('btn-check-update');
|
||
var msg = document.getElementById('update-status-msg');
|
||
btn.disabled = true;
|
||
btn.textContent = 'Frissítés...';
|
||
if (checkBtn) checkBtn.disabled = true;
|
||
msg.textContent = 'Frissítés folyamatban...';
|
||
msg.style.display = 'inline';
|
||
fetch('/api/selfupdate/update', {method:'POST', headers: csrfHeaders()})
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
if (data.ok) {
|
||
msg.textContent = 'Újraindulás...';
|
||
pollUntilBack();
|
||
} else {
|
||
msg.textContent = data.error || 'Hiba történt';
|
||
btn.disabled = false;
|
||
btn.textContent = 'Frissítés telepítése';
|
||
if (checkBtn) checkBtn.disabled = false;
|
||
}
|
||
})
|
||
.catch(function() {
|
||
msg.textContent = 'Kapcsolódási hiba';
|
||
pollUntilBack();
|
||
});
|
||
}
|
||
|
||
function resizeMemory() {
|
||
var input = document.getElementById('mem-input');
|
||
var target = parseInt(input.value, 10);
|
||
var current = parseInt(input.getAttribute('data-current'), 10);
|
||
if (isNaN(target) || target <= 0) {
|
||
showMemMsg('Érvénytelen memória érték', true);
|
||
return;
|
||
}
|
||
if (target < current) {
|
||
openDialog({title:'Memória csökkentése', confirmLabel:'Csökkentés',
|
||
message:'A memória csökkentése hatással lehet a futó alkalmazások teljesítményére. Biztosan folytatod?',
|
||
onConfirm:function(){ doResizeMemory(target); }});
|
||
return;
|
||
}
|
||
doResizeMemory(target);
|
||
}
|
||
function doResizeMemory(target) {
|
||
var btn = document.getElementById('btn-mem-resize');
|
||
btn.disabled = true;
|
||
btn.textContent = 'Átméretezés...';
|
||
fetch('/api/system/memory/resize', {
|
||
method:'POST', headers: Object.assign({'Content-Type':'application/json'}, csrfHeaders()),
|
||
body: JSON.stringify({memory_mb: target})
|
||
})
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
if (data.ok) {
|
||
showMemMsg(data.error || data.message || 'Kész.', false);
|
||
setTimeout(function(){ location.reload(); }, 1200);
|
||
} else {
|
||
showMemMsg(data.error || 'A művelet nem sikerült', true);
|
||
btn.disabled = false;
|
||
btn.textContent = 'Átméretezés';
|
||
}
|
||
})
|
||
.catch(function() {
|
||
showMemMsg('Kapcsolódási hiba', true);
|
||
btn.disabled = false;
|
||
btn.textContent = 'Átméretezés';
|
||
});
|
||
}
|
||
function showMemMsg(text, isErr) {
|
||
var msg = document.getElementById('mem-status-msg');
|
||
if (!msg) return;
|
||
msg.textContent = text;
|
||
msg.style.color = isErr ? 'var(--danger, #c0392b)' : 'var(--text-2)';
|
||
msg.style.display = 'inline';
|
||
}
|
||
|
||
function pollUntilBack() {
|
||
var iv = setInterval(function() {
|
||
fetch('/api/health')
|
||
.then(function(r) {
|
||
if (r.ok) {
|
||
clearInterval(iv);
|
||
location.reload();
|
||
}
|
||
})
|
||
.catch(function() {});
|
||
}, 3000);
|
||
}
|
||
|
||
// If an update is already in flight when the page loads (e.g. a floor-driven AUTO-update kicked off by
|
||
// the hub, not a button click), surface the same restart-poll panel so the page recovers itself.
|
||
{{if .UpdateRunning}}
|
||
pollUntilBack();
|
||
{{end}}
|
||
</script>
|
||
|
||
<!-- Section: Controller restart (self-serve) — always available (not gated on RetrievalPassword) -->
|
||
<div class="settings-card">
|
||
<h3>Vezérlő újraindítása</h3>
|
||
<p class="settings-card-desc">
|
||
Ha a vezérlő hibásan működik, itt biztonságosan újraindíthatja — nem kell az egész szervert újraindítani.
|
||
Az alkalmazásai futnak tovább; csak a vezérlő indul újra (néhány másodperc).
|
||
</p>
|
||
<div id="restart-status"></div>
|
||
<button type="button" class="btn btn-outline" id="btn-restart-controller" onclick="restartController()">Vezérlő újraindítása</button>
|
||
</div>
|
||
|
||
<!-- Section: Full server (guest) restart — a deliberate maintenance affordance, sibling to the controller restart -->
|
||
<div class="settings-card">
|
||
<h3>Kiszolgáló újraindítása</h3>
|
||
<p class="settings-card-desc">
|
||
Az egész kiszolgáló (szerver) újraindítása. Minden alkalmazás rövid időre leáll, és a vezérlőpult kb. 30 másodpercig nem elérhető. Akkor használja, ha a teljes rendszer újraindítására van szükség — egyébként a fenti „Vezérlő újraindítása” elegendő.
|
||
</p>
|
||
<div id="server-restart-status"></div>
|
||
<button type="button" class="btn btn-outline" id="btn-restart-server" onclick="restartServer()">Kiszolgáló újraindítása</button>
|
||
</div>
|
||
|
||
<script>
|
||
function restartController() {
|
||
openDialog({title:'Vezérlő újraindítása', confirmLabel:'Újraindítás',
|
||
message:'Biztosan újraindítja a vezérlőt? A művelet néhány másodpercig tart, és a felület rövid időre elérhetetlen lesz.',
|
||
onConfirm:doRestartController});
|
||
}
|
||
function doRestartController() {
|
||
var btn = document.getElementById('btn-restart-controller');
|
||
var status = document.getElementById('restart-status');
|
||
btn.disabled = true;
|
||
status.innerHTML = '<div class="alert alert-info">Újraindítás folyamatban… újracsatlakozás…</div>';
|
||
fetch('/api/selfrestart', { method: 'POST', headers: csrfHeaders() })
|
||
.then(function(){ pollRestart(0); })
|
||
.catch(function(){ pollRestart(0); }); // connection may drop as the process exits — poll regardless
|
||
}
|
||
function restartServer() {
|
||
openDialog({title:'Kiszolgáló újraindítása', confirmLabel:'Újraindítás',
|
||
message:'Biztosan újraindítja a kiszolgálót? Az alkalmazások és a vezérlőpult kb. 30 másodpercre elérhetetlenné válnak.',
|
||
onConfirm:doRestartServer});
|
||
}
|
||
function doRestartServer() {
|
||
var btn = document.getElementById('btn-restart-server');
|
||
var status = document.getElementById('server-restart-status');
|
||
if (btn) btn.disabled = true;
|
||
if (status) status.innerHTML = '<div class="alert alert-info">Újraindítás folyamatban… a vezérlőpult néhány másodperc múlva újratölt.</div>';
|
||
fetch('/api/server/reboot', { method: 'POST', headers: csrfHeaders() })
|
||
.then(function(){ pollRestart(0); })
|
||
.catch(function(){ pollRestart(0); }); // the guest reboot drops the connection — poll regardless
|
||
}
|
||
function pollRestart(attempt) {
|
||
if (attempt > 60) { // ~2 min cap — never leave the user on a dead page silently
|
||
document.getElementById('restart-status').innerHTML =
|
||
'<div class="alert alert-error">Az újraindítás a vártnál tovább tart. Töltse újra az oldalt kézzel.</div>';
|
||
return;
|
||
}
|
||
setTimeout(function(){
|
||
fetch('/', { method: 'GET', cache: 'no-store' })
|
||
.then(function(r){ if (r.ok) { window.location.reload(); } else { pollRestart(attempt + 1); } })
|
||
.catch(function(){ pollRestart(attempt + 1); });
|
||
}, 2000);
|
||
}
|
||
</script>
|
||
{{template "layout_end" .}}
|
||
{{end}}
|