Commit Graph
641 Commits
Author SHA1 Message Date
Safihre 3376cb5143 Escape the server-supplied NNTP message during testing 2026-09-14 22:24:09 +02:00
mnightingale 112d449446 Continue with the other RSS feed URIs when one fails 2026-09-11 14:35:33 +02:00
Safihre ab702860df Refactor color scheme implementation
Moves theme-specific styles into main CSS files for each interface,
leveraging `color-scheme` and `light-dark()` CSS functions. This
consolidates styling, reduces HTTP requests, and improves automatic
dark/light mode detection based on OS preferences.
2026-09-02 22:02:33 +02:00
mnightingale 4fde6e490c Update jQuery UI to 1.14.2 2026-08-31 16:32:13 +02:00
mnightingale 58c3c13954 Update jQuery to 3.7.1 2026-08-31 16:32:13 +02:00
mnightingale ecf5e27c04 Let the browser hold static files for good 2026-08-31 08:58:41 +02:00
mnightingale cd96dadcc3 Send the restart request below the configured URL base 2026-08-31 08:58:41 +02:00
Safihre 5696a667e7 Show in-progress status for server tests
Add an `alert-info` class to the result box while a server test is running,
providing visual feedback to the user that the process is ongoing.
2026-08-27 14:25:06 +02:00
mnightingale b192a7eca4 Persistent sessions, CSRF tokens, and no apikey in the web interface (#3559)
* Add a session store that keeps web-UI logins in the admin folder

* Authenticate the web interface with session cookies and CSRF tokens

* Stop embedding the apikey in the web interface

* Cover the session, CSRF and apikey changes
2026-08-27 13:05:12 +02:00
coopa11yandcoopa11y 21d639bf5f Announce news server test results to screen readers (#3566)
Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
2026-08-19 11:31:14 +02:00
coopa11yandcoopa11y 6d897a5f23 Announce notification test results to screen readers (#3567)
Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
2026-08-19 11:31:06 +02:00
Safihre 19b597d21b Add static cache busting for Config Auto colorscheme 2026-08-18 08:50:08 +02:00
mnightingale 583617f0a9 Fix submission of server forms when priority, displayname, or notes changes (#3578) 2026-08-17 20:57:42 +02:00
mnightingale cf26260910 Fix display of downloaded rss history (#3570) 2026-08-16 15:46:28 +02:00
mnightingale 35d5355f49 Replace CherryPy with Uvicorn and Starlette (#3550)
* Migrate web interface from CherryPy to Uvicorn/Starlette

Squashed rebase of feature/uvicorn (34 commits) onto develop, reconciled
with ~3 months of intervening develop changes.

Replaces the CherryPy webserver and request handling with Uvicorn/Starlette
across the API, web interface, RSS, config pages and related modules.

Reconciliation with develop during the rebase:
- api.py: kept develop's security/behaviour fixes (orphan path-traversal
  guard, expanded log redaction incl. host_whitelist and
  remote_label_replacement, get_dconfig single-return, get_retryable_jobs,
  connections default, translated NNTP test errors) on top of the Starlette
  request/response rewrite.
- interface.py: ported the RSS route handlers to develop's DB-backed
  RSSRepository API (process_feed, rss_repository / find_job_by_url /
  clear_feed / clear_downloaded / flag_downloaded).
- misc.py: kept develop's hachoir-based get_media_duration.
- requirements.txt: dropped the CherryPy stack, adopted develop's newer pins.

Also applied ruff --fix (PEP 604 unions, builtin generics) to align with
develop's lint config.

Verified: ruff check, black --check, and the affected test suites
(9413 passed, 1 skipped) all pass.

* Update starlette/uvicorn versions

* Fix race issues in global rss state

* Fix test race in server shutdown

The uvicorn migration turned /shutdown (and the shutdown API) into fire-and-forget: it spawned shutdown_program() in a background thread and replied immediately, whereas develop ran it synchronously and only replied once halt() had persisted all state. Because the module-scoped test teardown doesn't wait for the process to exit, the next module's clean_cache_dir wiped the shared cache dir (and reused the fixed port) while the previous instance was still saving state and holding the port — producing the three intermittent failures (deleted sabnzbd.log → "File log disabled or not found"; un-persisted [sorters] → KeyError; stale instance → missing wizard .quoteBlock).

* Fix robots and description, add favicon

* Remove remains of http basic auth

* Setup Starlette once configuration is available, fix static file relative cwd and url_base config

* abort_and_show_error when webserver fails to start

* Guard stopping webserver that never started

* Delegate XFF handling to ProxyHeadersMiddleware

* Merged params at request.state.params instead of modifying private apis

* Both shutdown routes share implementation and do not block event loop

* Run sync handlers via run_in_threadpool and facilitate eventual migration to async

* Pool database connections

* Online backup of database due to WAL changes

* Fix exception on None request.client (test clients or unix sockets)

* Fix flakey tests due to process not fully shutting down

* Restore X-Frame-Options behaviour via middleware

* Fix set_config_default with multiple keywords

* Remove broken logging call

* Restore api logging functionality

* Cache-Control: no-store

* Login only via POST

* Remove 401 (basic-auth) and add 404 handling via redirect

* Fix crash when shutdown not an int

* Use BaseRedirectResponse helper

* Remove trailing slashes from wizard routes

* URL helper, absolute URLs everywhere, fixes issues with nested navigation

* Fix scheduler adding multiple daysofweek

* Restore CherryPy api behaviour merging body with query params (body wins)

* Clearer documentation of get_request_params and request_params

* First stage supporting gradual api async

* Fix rss ajax consuming flash

* Restore access log functionality

* Hostname check in middleware

* Request logging in middleware

* Param parsing in middleware

* Security checks in middleware

* secured_expose is now purely route registration

* Lookup api handler once per request

* Fix flakey alert dialogs

* Trigger restart via BackgroundTask

* Restore CherryPy first param wins and get/post consistency

* Remove dead code

* Secure cookies based on protocol the client used

* Fix various issues with port_is_free

1. port_is_free answered the wrong question. It connect-probed ("is something answering?") rather than bind-probed ("can I bind?"). A port could report free and then kill startup at uvicorn's bind().
2. The bind-all remap crossed address families. :: was mapped to 127.0.0.1, probing IPv4 for an IPv6 bind — a regression against portend, which maps :: → ::1.
3. The call sites passed the wrong host. browserhost is a client-reachable address; the thing that has to be bindable is web_host.
4. Errors were swallowed. A bare except OSError hid gaierror, so an unresolvable host reported "free".
5. find_free_port had a port-0 trap. Under a bind-probe, currentport=0 always succeeds and returned 0 — the old failure sentinel. Now guarded, and None instead of 0.
6. Ports 80/443 were misdiagnosed. EACCES was folded into "occupied", producing ten futile probes and a panic claiming another program held the port. PermissionError now propagates to a dedicated panic explaining the actual remedies.
7. The tests were largely tautological. Three tests covering one branch, an IPv6 test with no IPv6 in it, a timeout test that never engaged the timeout, TOCTOU-prone fixed-range probes, no SO_REUSEADDR on the helper listener, and nothing asserting the property that matters — that "free" implies bindable.
8. A portability bug I introduced, then fixed. I'd baked Linux SO_REUSEADDR overlap semantics into four assertions; macOS differs. Now platform-aware, with the IPv6 regression re-covered by checking the socket family directly.

* Claim the bind address for uvicorn on startup, resolves "49" in err handling from cherrypy

* Rename function BaseRedirectResponse to base_redirect_response

* Restore error response on change web directory

* Add missing typings

* Fix return type of retry job for future types

* A better fix for xdist compatibility - test overwrote db_path

* Secure session cookies (rss flash)

* Inline or remove some functions

* Retry job futuretype behaviour

* Sneak a worksteal fix in

* Test and fix retry_job futuretype behaviour
2026-08-11 13:27:51 +01:00
coopa11yandcoopa11y fd191d1b79 Add screen reader names to Glitter and Config dialogs (#3545)
Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
2026-08-10 12:25:17 +01:00
Safihre 40860c68ca Correct Notifications page display 2026-08-08 21:34:48 +02:00
Safihre b8838c4728 Improvements to Notification options display 2026-08-07 11:03:39 +02:00
Safihre 78cb553b14 Fix config UI selection and update direct unpack log message
Correctly pre-select the 'all' option for `history_retention_option` in the config UI by using the correct variable.
2026-08-06 16:15:09 +02:00
coopa11yandcoopa11y 0411e8acc1 Label schedule time, enable, and delete controls for screen readers (#3525)
* Label schedule time, enable, and delete controls

* Use ARIA label for schedule enable control

---------

Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
2026-07-28 21:12:47 +03:00
coopa11yandcoopa11y 9122633907 Label SABnzbd login fields and help link for screen readers (#3524)
* Label SABnzbd login fields and help link

* Use ARIA labels for login fields

---------

Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
2026-07-28 17:42:48 +03:00
Parsa YazdaniandQuixThe2nd 404060373b feat: add 'Sort by Remaining Size' queue sort option (#3512)
* feat: add 'Sort by Remaining Size' queue sort option

Add a new 'remaining_bytes' sort field that sorts the queue by absolute
remaining bytes (bytes - bytes_tried), complementing the existing
'remaining' sort which uses percentage downloaded and the 'size' sort
which uses total bytes.

Changes:
- nzbqueue.py: add remaining_bytes sort field, fix update_sort_order()
  to parse field+direction from config instead of hardcoding 'remaining'
- skintext.py: add Glitter-sortRemainingBytesAsc/Desc translation strings,
  update auto_sort explanation text
- Glitter UI: add dropdown entries and JS handlers for both directions
- Config: add auto_sort options for remaining_bytes asc/desc
- Tests: parametrize remaining_bytes asc/desc against sizeleft slot field

* style: wrap long string for Black formatting

* fix: limit remaining-size sorting to ascending

---------

Co-authored-by: QuixThe2nd <QuixThe2nd@users.noreply.github.com>
2026-07-26 16:28:08 +03:00
mnightingale ba2099d006 Add RSS Age rule (#3498)
* RSS age rule

* Support years (y) and months (mo) and do not approximate durations in seconds

* Better handling of entries with no age

* Formatting

* Allow >=, =>, <=, and =< aliases

* Implement feedback

* Fix existing issue with From SxxEyy in default row

* Test unitless ages
2026-07-16 21:24:41 +02:00
Safihre dc421047d3 Render Config UI tooltips in body
Closes #3486
2026-07-04 20:32:28 +02:00
coopa11yandcoopa11y fd6d8c71c7 Improve Config search accessibility (#3476)
Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
2026-07-03 13:07:20 +02:00
Safihre fee562d57f Increase default NNTP server connections to 16
Updates the default number of connections from 8 to 16 in the server configuration and wizard UI templates. This change aims to improve performance for users who do not explicitly configure this setting.

Additionally, ensures the API server test function defaults to at least 1 connection when none is specified.

Relates to #3284
2026-06-14 13:34:22 +02:00
Safihre e969276828 Extend custom toggle switch styling to login and wizard 2026-06-11 11:40:11 +02:00
Safihre e3acbdc8c2 Use commit hash for static asset cache busting
Closes #3457
2026-06-11 11:10:43 +02:00
Safihre 83d167415a Refine toggle styling implementation for Firefox compatibility
Replaces the `::after` pseudo-element with CSS `background-image` properties to draw the toggle's movable knob and its shadow.
2026-06-08 16:58:22 +02:00
Safihre 5c4d2f1d9f Improve on toggle redesign 2026-06-08 15:38:08 +02:00
Safihre 09c338dd5b Change checkboxes in Config to toggle 2026-06-08 14:44:31 +02:00
Safihre bff7d559f9 Refine button and navigation tab interactive states 2026-06-08 09:04:29 +02:00
Safihre 08bcddf8d2 Style login and wizard pages after recent changes 2026-06-05 14:32:04 +02:00
mnightingale 2c530fee47 Remove disableDelays because config is not defined (#3438) 2026-05-26 06:50:24 +02:00
Safihre f12725eea5 Adjust new rounded UI layout and spacing for consistency
Refines margins, paddings, and element positioning across various components to improve visual harmony and alignment with the modernized interface design.
2026-05-23 22:17:28 +02:00
Safihre dbf8ef15ef Refactor theming to use CSS variables
This modernizes the theming architecture by defining core colors as CSS variables,
allowing themes like 'Night' to override them concisely. This approach improves
maintainability and removes dynamic styling previously handled by JavaScript.
2026-05-23 22:05:46 +02:00
Safihre de5abc95f5 Further improvements to styling revamp 2026-05-23 22:05:45 +02:00
Safihre e63648c9c4 Give the Config a little bit more modern feeling 2026-05-21 10:06:01 +02:00
mnightingale 2184964d78 Reduce time to test (#3412)
* Remove UI delays

* Everything using set_config, set_platform, or pyfakefs

* tmp_path

* Scroll to top seems unnecessary but make it wait until it's done

* Remove sleep from test_rss_basic_flow

* Remove sleeps from test_daemonizing

* Define pytest markers

* Reduce sleep in test_queue_repair

* Remove sleeps from clean_cache_dir

* Suppress failures to connect during startup

* Reduce cache sleeps

* Reduce sleeps checking app started

* Reduce sleep removing cache dir
2026-05-13 18:49:41 +02:00
Safihre f7ad95f298 Consolidate RSS feed processing and remove 'Apply filters' action
Performance of Apply Feed is good enough that we can run it on any filter change.
2026-05-13 13:59:17 +02:00
Safihre cd5acde5d2 Set pipeling requests to 2 for new servers (#3362) 2026-03-23 22:51:02 +01:00
Safihre 2122503762 Update copyright to 2026 2026-02-09 16:44:38 +01:00
Safihre 9624a285f1 Add Apprise documentation URL to Notifications page 2026-01-26 10:45:11 +01:00
Safihre 6487944c6c Move Pipelining setting to Server-level 2025-12-22 16:38:46 +01:00
Safihre daca14f97e Update Apprise texts 2025-11-03 14:28:47 +01:00
Safihre d989ec928a Small styling issue for tooltip in Night mode 2025-10-14 11:12:06 +02:00
Safihre c1417c319d Add tooltip that users need to Test Server before saving/next 2025-10-13 16:24:04 +02:00
Safihre 3393d7c976 Changing server name shows button "failure" instead of "saving..."
Closes #1551
2025-10-06 15:54:11 +02:00
Safihre ec18606557 Require correct server test in Wizard
Closes #3148
General refactor.
2025-09-25 13:40:25 +02:00
Matt Miller 0b295d7b57 Update to_units and quota api output format (#3076)
* Include byte unit in quota strings

Fixes #2590

I expect to continue to iterate on some of the ideas in the comments
thereon, but this fixes the proximate issue mentioned in the issue.

This includes changes to the interface to properly interpret the new
strings:

- Remove the UI-based `B` designations as they are now tagged with
  units from the api
- Let parseInt do its magic with string-y numbers plus units
- Expand parseInt for use in the checking whether quota is set

The display will be better in this `Glitter` case. This may well be
considered a breaking change for the API and not applied.

* Reduce computation slightly

No need to iterate over the evenly spaced unit sizes.
We can determine its magnitude quickly and convert it
into an index for our tags.

Avoiding the repeated divisons might also reduce error, but it is
unlikely to be noticeable.

* Drop trailing space when no units

The issue didn't expressly complain, but there is a trailing space when
all of the other unit information is empty.  Might as well not include
it when it clearly will happen.

The use of `f-strings` might also simplify future maintenance.

* Better document to_units methodology

This addresses some code review concerns with respect to readability.
Frankly, having this much exposition in the comments might imply that
it's a lot less obvious than I thought at initial writing.

This also maps everything under `1024` directly to `0`.  This avoids
concerns about potentially generating negative indices into the tags
tuple which would be surprising and wildly incorrect.
2025-04-26 11:39:10 +02:00