Fix reboot flow: add /api/ping, fix waitForServerReboot polling, fix security.js handler

Agent-Logs-Url: https://github.com/naturallaw777/staging_alpha/sessions/ee8673cf-ad65-4f65-b5c8-2f170e78022f

Co-authored-by: naturallaw777 <99053422+naturallaw777@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-04-14 00:02:45 +00:00
committed by GitHub
parent c5bbb5220e
commit 7576c0fe85
3 changed files with 14 additions and 9 deletions

View File

@@ -87,7 +87,7 @@ LOGIN_FAIL_WINDOW = 60.0 # rolling window (seconds) for counting failures
LOGIN_FAIL_MAX = 10 # max failures in window before extra delay LOGIN_FAIL_MAX = 10 # max failures in window before extra delay
# Public paths that are accessible without a valid session # Public paths that are accessible without a valid session
_AUTH_EXEMPT_PATHS = {"/login", "/api/login", "/api/updates/status", "/api/rebuild/status", "/auto-login"} _AUTH_EXEMPT_PATHS = {"/login", "/api/login", "/api/updates/status", "/api/rebuild/status", "/auto-login", "/api/ping"}
# Prefixes for static assets required by the login page # Prefixes for static assets required by the login page
_AUTH_EXEMPT_PREFIXES = ("/static/css/", "/static/sovran-hub-icon.svg") _AUTH_EXEMPT_PREFIXES = ("/static/css/", "/static/sovran-hub-icon.svg")
@@ -2596,6 +2596,11 @@ async def api_updates_check():
return {"available": available is not False} return {"available": available is not False}
@app.get("/api/ping")
async def api_ping():
return {"ok": True}
@app.post("/api/reboot") @app.post("/api/reboot")
async def api_reboot(): async def api_reboot():
try: try:

View File

@@ -161,6 +161,8 @@ function openSecurityModal() {
rebootBtn.disabled = true; rebootBtn.disabled = true;
rebootBtn.textContent = "Rebooting\u2026"; rebootBtn.textContent = "Rebooting\u2026";
if ($rebootOverlay) $rebootOverlay.classList.add("visible"); if ($rebootOverlay) $rebootOverlay.classList.add("visible");
_rebootStartTime = Date.now();
_serverWentDown = false;
setTimeout(waitForServerReboot, REBOOT_INITIAL_DELAY); setTimeout(waitForServerReboot, REBOOT_INITIAL_DELAY);
var rebootCtrl = new AbortController(); var rebootCtrl = new AbortController();
setTimeout(function() { rebootCtrl.abort(); }, REBOOT_REQUEST_TIMEOUT); setTimeout(function() { rebootCtrl.abort(); }, REBOOT_REQUEST_TIMEOUT);

View File

@@ -185,21 +185,19 @@ function waitForServerReboot() {
var controller = new AbortController(); var controller = new AbortController();
var timeoutId = setTimeout(function() { controller.abort(); }, REBOOT_FETCH_TIMEOUT); var timeoutId = setTimeout(function() { controller.abort(); }, REBOOT_FETCH_TIMEOUT);
fetch("/api/config", { cache: "no-store", signal: controller.signal, headers: { "Connection": "close" } }) fetch("/api/ping", { cache: "no-store", signal: controller.signal, headers: { "Connection": "close" } })
.then(function(res) { .then(function(res) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (res.ok && _serverWentDown) { if (_serverWentDown) {
// Server is back after having been down — reboot is complete // Server is responding after having been down — reboot is complete.
// Any response (even 401/500) means the server process is back.
window.location.reload(); window.location.reload();
} else if (res.ok && !_serverWentDown && (Date.now() - _rebootStartTime) < 90000) { } else if ((Date.now() - _rebootStartTime) < 90000) {
// Server still responding but hasn't gone down yet — keep waiting // Server still responding but hasn't gone down yet — keep waiting
setTimeout(waitForServerReboot, REBOOT_CHECK_INTERVAL); setTimeout(waitForServerReboot, REBOOT_CHECK_INTERVAL);
} else if (res.ok) { } else {
// Been over 90 seconds and server is responding — just reload // Been over 90 seconds and server is responding — just reload
window.location.reload(); window.location.reload();
} else {
_serverWentDown = true;
setTimeout(waitForServerReboot, REBOOT_CHECK_INTERVAL);
} }
}) })
.catch(function() { .catch(function() {