Commit Graph
5 Commits
Author SHA1 Message Date
maziggy a4795c5ca3 Let API keys read and run slicer pipelines (#1425 follow-up)
Every pipeline endpoint answered 403 for API keys whatever scopes the key
carried. PR A parked all three permissions on the admin denylist until the
run dispatch existed to decide about; it landed in PR C and the parking was
never revisited.

PIPELINES_READ now rides can_read_status. PIPELINES_RUN requires
can_queue AND can_manage_library together, so the allowlist gained tuple
values: a run slices into the library and then queues prints, and mapping
it to either flag alone would hand that flag the other one's authority.
The 403 names every flag the key is short of. PIPELINES_WRITE stays
admin-only -- a key can run the recipe, not rewrite it or clear the log.

Opening the run route also needed the cloud-owner fallback the direct
slice route makes: a pipeline can carry Bambu/Orca Cloud presets, and
resolving those reads a token off a user record that an API-keyed request
does not have. retry_failed forwards the new dependency explicitly,
since a direct call receives the Depends marker rather than None.
2026-08-15 10:38:51 +02:00
maziggy 77135aaf8f Fix unawaited coroutine warning in printer offline notification tests
on_printer_status_change builds reconcile_stale_active_prints(...) as a
call argument, so the coroutine is constructed even when the spawn helper
is mocked out. A bare MagicMock retained it in call_args and it finalised
unawaited during a later test's GC, surfacing as a
PytestUnraisableExceptionWarning attributed to test_printer_sensor_history.

Patch spawn_background_task with a side_effect that closes the coroutine,
and correct the _state() docstring, which claimed state="IDLE" kept the
reconcile-edge branch quiescent when it does the opposite.
2026-08-02 10:23:09 +02:00
maziggy a5176349dd fix(notifications): capture the snapshot outside the DB session (#2572)
The progress-milestone and HMS-error notification paths in
on_printer_status_change held a session across the ~15s camera snapshot
taken for the notification image, pinning a pooled connection per
milestone/error per printer.

The snapshot needs no DB: read the printer in a short session, release
it, grab the snapshot with none held, then open a fresh session for the
notification send (and lift the db-free MQTT publish out too). Pinned by
a test that fails if the snapshot runs while a session is open.
2026-07-16 09:20:12 +02:00
maziggy b1cb26f6ee feat(ams-backup): add status badge + toggle, fix prefer-lowest (#1766)
Two tightly-coupled deliverables in one drop -- a new AMS Filament Backup
  status/control surface, and the #1766 fix that depends on it.

  Added -- AMS Filament Backup status + control
  - Parse bit 18 of top-level print.cfg into PrinterState.ams_filament_backup
    on every push_status. Verified against OrcaSlicer source
    (DeviceManager.cpp:4961) and a live H2D ON/OFF capture. Tri-state
    (None = A1 family / pre-cfg push) preserves today's behaviour.
  - Hold-timer guard (3 s) prevents stale frames from flickering the badge
    back to the printer's old cfg after a user-initiated toggle.
  - POST /printers/{id}/ams-backup toggle, set_ams_filament_backup() client
    method calling _set_print_option("auto_switch_filament", enabled).
  - GET /printers/{id}/inventory-remain endpoint exposes the same map the
    dispatcher uses (internal and Spoolman modes both work uniformly).
  - Small icon badge in the printer card's "Filaments" section header
    (placement reads as printer-wide because the cfg bit is printer-wide,
    not per-AMS). Click to toggle, success toast.
  - 5 i18n keys x 11 locales for the badge UI.

  Fixed -- #1766: prefer_lowest didn't pick lowest, ignored backup state
  - Backend gate in _compute_ams_mapping_for_printer: coerce prefer_lowest
    to False when status.ams_filament_backup is False; log the skip.
  - New effectivePreferLowest(setting, backup) helper applied at every
    frontend sort entry point: single-printer PrintModal, multi-printer
    hook per-printer, PrinterSelector InlineMappingEditor, FilamentMapping
    standalone editor (the last had NO preferLowest awareness at all
    before this change).
  - New preferLowestSortKey(f, inventoryByTrayId) mirrors backend's two-tier
    key exactly, including the banding tie-break (regular AMS < AMS-HT <
    external) so the client-side pre-compute matches the dispatch-time pick.
    An earlier draft used a flat `amsId * 4 + trayId` priority which gave
    external slots (ams_id = -1) a NEGATIVE priority -- caught in code
    review before commit.
  - Settings -> Filament -> "Prefer lowest remaining filament" gets an
    explanatory note about the printer-side AMS Backup dependency, with
    i18n key in all 11 locales.
2026-06-20 12:07:20 +02:00
maziggy ead6c37147 fix(notifications): wire on_printer_offline dispatch on disconnect edge (#1752)
The provider toggle, schema, template, and NotificationService.on_printer_offline
  all shipped, but no caller invoked the dispatcher — the offline event was an
  orphan toggle. Edge detection in on_printer_status_change now schedules a
  debounced (60s) background task on the connected→disconnected transition;
  reconnect before the window elapses cancels it. Covers both upstream paths
  (smart-plug power-off via mark_printer_offline, and MQTT staleness via
  check_staleness), both of which already route through the status callback.
  The "back online" channel is the existing print-failure notification on
  firmware FAILED report — no symmetric on_printer_online needed.
2026-06-16 07:34:14 +02:00