base.html passed the cache-busting query string INSIDE the filename argument:
url_for('static', filename='uploads/header_logo.png?v=1')
Flask percent-encodes the '?' to '%3F', producing a request for a file
literally named "header_logo.png%3Fv=1", which does not exist. Every
authenticated page therefore logged:
GET /static/uploads/header_logo.png%3Fv=1 404
The logo silently stayed hidden too, because the element carries
onerror="this.style.display='none'".
Changes:
- base.html / login.html: append "?v=..." OUTSIDE url_for(), matching what
admin/customize_logos.html already did correctly.
- Inject logo_version from a context processor instead of hardcoding it.
It is derived from the newest logo's mtime, so uploading a new logo in
Admin -> Customize Logos is reflected immediately. The previous value was
a literal 1, which defeated cache-busting entirely; login.html used
range(1, 999999) | random, which changed on every request and made the
logo uncacheable.
Verified: /, /content/ and /players/ now render
/static/uploads/header_logo.png?v=<mtime> (HTTP 200), and no %3F requests
appear in the logs.
- Changed ownership of all files to scheianu:scheianu
- Set directories to 755 permissions (rwxr-xr-x)
- Set files to 644 permissions (rw-r--r--)
- Made shell scripts executable (755)
- Allows development without requiring sudo for file modifications
- Improves development workflow and security