small web UI improvements#34
Merged
tridge merged 4 commits intoArduPilot:mainfrom May 10, 2026
Merged
Conversation
Drop <meta http-equiv="refresh"> from the four live views and have new static/auto-refresh.js poll the same URL every N seconds (set via <body data-auto-refresh="N">) and swap the <main> element in place via DOMParser. The <header> (logo, nav, log-out) is outside <main> so it never re-renders — no flash on the auto-refresh. Firefox's behaviour was the trigger: it doesn't paint-hold across full-page navigations the way Chrome does, so even with the static asset Cache-Control header in place the entire page (including the ArduPilot logo) blanked for a frame on every meta-refresh tick. Helpers (localtime.js, password-toggle.js) listen for the new 'pageupdate' event auto-refresh.js dispatches after each swap, so any newly-injected <time> or password input picks up the same treatment as on initial load. The polling skips ticks when document.hidden is true so backgrounded tabs don't burn cycles, guards against overlapping in-flight requests, and uses redirect: 'manual' so a 302 to /login (e.g. session expired) stops the swap rather than injecting a login form into the live view. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The browser cache header introduced for the logo flash fix (SEND_FILE_MAX_AGE_DEFAULT = 86400) also applied to the tlog download route, so each downloaded telemetry file came back as Cache-Control: public, max-age=86400. On a shared device or behind an intermediary cache that's a real exposure window for vehicle telemetry — flagged by codex review. Override on the download path only: pass max_age=0 to send_from_directory and replace the response's Cache-Control with 'private, no-store' (plus a Pragma: no-cache for legacy proxies). Logo/CSS/JS keep the 24h cache so the auto-refresh still doesn't flash the header. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The /login route had no rate limit or lockout — flagged by codex
review. Anyone reaching the public listener could grind through
passphrases as fast as the server would answer.
Two layers, in-memory:
* Constant 0.5 s sleep on every failed login. Caps single-IP
throughput at ~120/min regardless of the counter.
* Per-IP sliding-window failure counter (60 s window, 10
failures). Once exceeded, further attempts from that IP are
rejected with "Too many failed login attempts" — even if the
passphrase is correct — until the window expires. A successful
login clears the IP's history so a few user typos don't lock
them out for a full minute.
Skipped under app.config['TESTING'] so the existing webadmin suite
(many sequential login_as calls from 127.0.0.1) doesn't trip it.
Counters live in a process-local dict guarded by threading.Lock —
fine for the small admin UI; bigger deploys should swap in
flask-limiter with a redis backend.
5 new tests cover: success resets the counter, threshold blocks
even with the right passphrase, separate IPs don't share state,
the sliding window expires correctly, and TESTING short-circuits
the throttle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous rsync swept the whole working tree, relying on an allow-list of excludes to keep secrets out. Codex review flagged it: generic scratch (pass.dat, x.dat, way.txt), local-only scripts, *.orig from a recent merge etc. weren't covered, so a fresh untracked file in the local cwd would silently ship. Switch to deny-by-default. Build a temporary staging tree from 'git ls-files --recurse-submodules' (so modules/mavlink/* lands along with the top-level files), filter out paths that resolve to a directory (uninitialised nested submodules — cp without -r would otherwise fail), then rsync that staging tree to the remote. Local dry-run confirms pass.dat / x.dat / way.txt / .webadmin_secret / fullchain.pem / keys.tdb / AGENTS.md / *.orig / *.rej / etc. all stay behind, while the 477 tracked files (including the mavlink submodule and .git/) ship correctly. Uncommitted edits to TRACKED files still go through; only NEW files now have to be git add'd before they're deployable, which is reasonable hygiene. RSYNC_EXCLUDES is unchanged — the staging side is already clean, so the excludes' job is now just protecting server-side state (keys.tdb, *.pem, logs/, .webadmin_secret) from --delete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.