github spl0k/supysonic 0.8.0

51 minutes ago

A large release: most of the codebase has been reviewed for security, performance and correctness, and Supysonic can now be extended with third-party scrobblers, lyrics providers and cover art providers.

Upgrade notes

  • Back up your database first. Migrations run automatically on startup and convert playlists, user passwords and scrobbling account links. Once a user has logged in, their password can't be read by older versions: downgrading requires restoring the backup
  • Playlist entries pointing to tracks that no longer exist are dropped during the migration
  • Run a scan of your folders afterwards so file sizes get recorded (--force isn't needed)
  • Upgrade and restart the web application and the daemon together: their communication format changed and versions can't be mixed
  • index_ignored_prefixes moved from [webapp] to the new [api] section. The old location still works for now but logs a warning
  • If you run supysonic-server directly exposed to the network, pass --host 0.0.0.0 (or the address you want) as it now only listens on localhost by default

Changes

Added:

  • Pluggable scrobblers, lyrics providers and cover art providers, selected in the new [plugins] configuration section. Last.fm, ListenBrainz, embedded and sidecar lyrics, folder and embedded covers are all built on this.
    Writing your own is documented under Extending Supysonic
  • Option to answer failed API requests with a matching HTTP error status ([api] use_http_error_status, off by default since some clients don't like it)
  • Last.fm API URL can be configured
  • Verified support for Python 3.13, up to 3.15

Improvements:

  • Much faster API on large libraries: playlists are now stored as proper database rows (no more slow getPlaylists with long playlists), annotations (stars, ratings) and related data are fetched in batches, and file sizes are stored in the database instead of being read from disk on every listing
  • Stronger password hashing; existing passwords are upgraded transparently on the user's next login
  • Paginated endpoints (album lists, search) now return stable pages
  • Email addresses are checked everywhere, and no longer required when creating a user through the API
  • Configuration values are checked when the configuration is read: an invalid value is reported at startup instead of failing later
  • Scrobbling services now receive a proper identification of Supysonic
  • Lyrics lookup on large libraries is bounded

Security:

  • CSRF protection on the web interface, and every action that changes something now requires a POST request
  • Session cookies are HttpOnly and SameSite=Lax
  • No more open redirect on the web interface login page
  • Protection against timing attacks on authentication (including user enumeration)
  • Fixed a possible remote code execution through the daemon socket (required access to both the socket and the daemon key)
  • Fixed a path traversal through the transcoding cache
  • Fixed HTTP header injection
  • Error responses no longer leak internal details, these go to the log
  • supysonic-server now listens on localhost by default instead of all
    interfaces

Fixes:

  • Fixed oggdec usage in the sample transcoding configuration
  • Fixed the watcher mishandling its queue and its timing
  • Fixed an error deleting a folder containing tracks used in a playlist
  • Fixed getStarred on PostgreSQL
  • Fixed configuration files overwriting defaults with untyped values
  • Fixed failures when the cache directory gets deleted while running
  • MySQL/MariaDB dates now keep their sub-second precision
  • Various small fixes in the scanner, jukebox and daemon

Removed:

  • ChartLyrics integration, the service no longer exists. The online_lyrics option is now ignored
  • Support for Python 3.9 and below

Note to package maintainers

  • Packaging now relies solely on pyproject.toml; setup.py, setup.cfg and MANIFEST.in are gone
  • The source distribution no longer ships prebuilt man pages nor config.sample, and the wheel no longer installs man pages. Both come from the source tree (git tag archive): see PACKAGING.md
  • New dependency: flask-wtf. werkzeug is now declared explicitly. Every dependency has a minimum version, checked in CI

Don't miss a new supysonic release

NewReleases is sending notifications on new releases.