feat: custom wallpaper background with brightness adjustment - #624
renheqiang wants to merge 11 commits into
Conversation
|
This is a well-scoped, well-documented PR. The feature is genuinely useful and the implementation is thorough. A few questions and observations before merge: Architecture ✅The layered approach ( Magic-byte validation ✅The strict rejection approach (RIFF+WEBP offset check, explicit rejection of SVG/HTML) is the right security posture for a server that serves back user-uploaded files. The mis-tagged AVI/WAV edge case catch is a nice detail.
|
…nsive
When _settingsDirty is true, clicking the X button shows the unsaved-
changes bar instead of closing the modal. Previously the bar was
prepended into .settings-main with no scroll/visibility hint, so users
who had scrolled past the top of the panel saw no reaction at all.
Newly observed because the wallpaper batch added a brightness slider
whose input event marks dirty — easier to land in this state.
Fix:
- position:sticky;top:0;z-index:5 keeps the bar visible regardless
of scroll position inside the settings body
- scrollIntoView + brief flash/scale animation on (re)show so even
a repeat click on X gives clear feedback
- stronger background + backdrop-filter for visual weight
|
The new commit On the earlier open questions from my first review — following up on items 3 and 6 which I flagged as most important: Item 3 (server-side brightness clamp): If the dedicated concurrent-write test confirms the validator rejects out-of-range values at the server layer (not just client-side), that's sufficient. Just confirming the test isn't only exercising a JS clamp. Item 6 (frontend URL update on re-upload): After uploading a new wallpaper (new hash → new filename), does the frontend update both the Once those two are confirmed, this is ready to merge. The overall implementation quality is high. |
|
Good feature concept and solid test coverage (16 pytest + 21 E2E). Three blockers to fix before merge: Required:
Strengths worth noting: magic-byte validation is solid (WebP double-check is correct), 10MB cap enforced at both client and server, caching with immutable headers + hash-based filenames is the right approach, test coverage is thorough. |
The first reviewer flagged that wallpaper_file is in _SETTINGS_ALLOWED_KEYS
but had no validator. An authenticated user could POST /api/settings with
{"wallpaper_file": "/etc/passwd"} or {"wallpaper_file": "../../foo.jpg"}
and the value would persist. GET /api/wallpaper would then attempt to
serve it; the magic-byte sniff in read_wallpaper blocks /etc/passwd-style
non-image files, but ANY image file readable by the webui process anywhere
on disk (e.g. another user's avatar, screenshots in /tmp) would leak.
Fix: add an anchored regex validator in save_settings that requires the
value to either be None (clears the wallpaper) or match the exact format
save_wallpaper() writes: wallpaper-<8 hex>.{jpg,png,webp}. Same pattern
already used for language code validation.
Added two regression tests covering:
- 12 invalid inputs (paths, traversal, wrong extensions, types, etc.)
are silently rejected without overwriting the prior value
- All three valid extensions round-trip correctly
- None correctly clears the field
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Independent End-to-End Review — PR #624Independent review picking up the path-traversal blocker from the prior reviews. Pushed a fix. TL;DROne blocker fixed, two remaining for maintainer/author. Pushed a Path traversal blocker — FIXED ✅The first reviewer correctly identified that The magic-byte
Fix pushed in Regression tests added (12 invalid inputs verified rejected):
Plus a positive test confirming all three valid extensions round-trip. Other items from the prior review threadItem from review-2 ("merge sequence with #627") — not addressed by me. PR #627 introduces the new theme/skin axis system; this PR's
#629 polish follow-ups — already tracked as a separate issue, not blocking. Tests ✅
Security audit ✅ (after fix)
Summary
Path traversal blocker is closed. Remaining open items are coordination-with-other-PRs concerns rather than issues with this PR's content. |
|
Quick status: the path-traversal blocker was fixed by the prior reviewer (commit d1c764f). Two items remain before merge: (1) CSS coordination with the skin/theme system (#627/#629) — the wallpaper brightness CSS may conflict with the CSS variable approach used in the theme system; and (2) the wallpaper should degrade gracefully when the stored file is deleted or moved. If you'd like to continue, a rebase onto current master (v0.50.92) is the first step. Happy to assist with the rebase. |
Summary
settings.jsonvia the existing/api/settingsPOST flow..svg/ HTML / mis-tagged containers regardless of clientContent-Type. WebP requires bothRIFFprefix ANDWEBPat offset 8 (catches mis-tagged AVI/WAV).save_settingsby adding_SETTINGS_WRITE_LOCK(covered by a dedicated concurrent-write test).Architecture notes
~/.hermes/webui/wallpaper-<sha1[:8]>.{ext}; filename hash doubles as cache buster (Cache-Control: public, max-age=31536000, immutable).<div id="wallpaper">atposition:fixed; z-index:-1withfilter: brightness(var(--wallpaper-brightness)).background:var(--bg)frombodytohtml, setsbody{background:transparent}. Theme color is the bottom-most fallback layer; semi-transparent chrome (.main,.topbar,.composer-wrap) composites the wallpaper through.POST /api/wallpaper,POST /api/wallpaper/delete,GET /api/wallpaper,GET /api/wallpaper/info) in 1 new moduleapi/wallpaper.py.Content-Type— simpler than multipart for a single-file upload, no coupling to existingparse_multiparthelper.Test plan
tests/test_wallpaper.py: 7 unit (storage module + magic-byte) + 6 HTTP (endpoints + cache headers + error responses) + 3 settings (brightness range validator + concurrent write race)test_model_resolverfailures unrelated)TESTING.mdunder "Wallpaper" (14 items)Notes for reviewer
body{background}→html{background}swap is its own commit (7a22ab5) for easy bisect if any visual regression appears._SETTINGS_WRITE_LOCK(20abf8d) closes a load-merge-write race that affected ALL settings POSTs, not just wallpaper. Marked as bonus fix in the commit message.🤖 Generated with Claude Code