Commit Graph
258 Commits
Author SHA1 Message Date
maziggy 51f08a5c86 Suppress Bandit false positives in virtual printer and tests
B108: /tmp paths in test mocks (not real filesystem access).
B104: string comparisons against "0.0.0.0" (not socket binds).
2026-02-10 17:41:16 +01:00
maziggy 142c7f99f6 Merge branch 'feature_user_authentication' of https://github.com/cadtoolbox/bambuddy into test-merge
# Conflicts:
#	frontend/src/components/ConfigureAmsSlotModal.tsx
#	frontend/src/i18n/locales/ja.ts
#	static/index.html
2026-02-10 16:40:10 +01:00
maziggy 7f22260c90 Fix H2C nozzle rack wrong empty slot, missing filament colors, and medium card layout (#300)
Three fixes for the H2C nozzle rack reported by testers:

1. Empty slot position: rack nozzles were mapped by sequential array
   index instead of by actual nozzle ID (16-21), so a missing slot
   always appeared at position 6 instead of its real position. Now
   maps each nozzle to its correct rack position via id offset.

2. Missing filament colors/materials: the H2C MQTT payload uses
   different field names than H2D — color_m (not filament_colour),
   fila_id (not filament_id), sn (not serial_number), tm (not
   max_temp). Added fallback field name resolution in the backend
   MQTT parser.

3. Medium card layout: the temperature row with nozzle rack overflowed
   on medium-sized cards. Added flex-wrap and a 190px flex-basis on
   the rack card so it wraps to a second line when space is tight.
2026-02-10 14:05:55 +01:00
maziggy c5fff9bc15 Fix AMS-HT mapping for left nozzle on H2D Pro (#318)
AMS-HT global tray ID was calculated as ams_id * 4 (= 512 for unit 128)
but AMS-HT uses the raw ams_id directly since it has a single tray.
The backend misidentified 512 as an external spool, producing wrong
ams_mapping2. Fixed in 4 locations: frontend getGlobalTrayId(), backend
start_print() ams_mapping2 builder, print scheduler, and Spoolman tracking.
2026-02-10 13:54:21 +01:00
maziggy 94ba65e3bc Fix H2C nozzle rack display and add L/R hover cards (#300)
Rack card now shows 6 rack-only slots (IDs 16-21) with empty placeholders,
excluding L/R hotend nozzles. New DualNozzleHoverCard shows both nozzle
details side-by-side with Active/Idle status. Single-nozzle H2 printers
get extended hover details. Backend stores nozzle_info for all H2 series.
Added i18n keys (en/de/ja) and 10 tests (7 backend + 3 frontend).
2026-02-10 13:40:03 +01:00
maziggy 30b8887e79 H2C nozzle rack: show all 6 nozzles, translate types, add flow & filament (#300)
- Show all 6 nozzles including mounted: backend includes all nozzle_info
  entries (removes id >= 2 filter), frontend filters to non-empty
- Translate nozzle type codes to full names: HS→Hardened Steel, 00/01/05
  mapped to Stainless Steel/Hardened Steel/Tungsten Carbide
- Add flow type to hover card: HH→High Flow, HS→Standard
- Show filament material type in hover card (PLA, PETG etc.) from MQTT
  tray_type/filament_type field
- Add filament_type to NozzleRackSlot schema (backend + frontend)
- Add translations (en, de, ja, it): nozzleTungstenCarbide, nozzleFlow,
  nozzleHighFlow, nozzleStandardFlow
2026-02-10 11:34:12 +01:00
maziggy 516841a7f5 Fix virtual printer IP override ignored in server mode (#52)
The remote_interface_ip setting only worked in proxy mode but was
completely ignored in server modes (immediate/review/print_queue).
Users with multiple NICs (LAN + Tailscale, Docker bridges) got wrong
auto-detected IP in SSDP broadcasts and TLS certificates.
2026-02-10 10:05:35 +01:00
maziggy ae63ec8a91 Fix H2C firmware update downloading wrong (H2D) firmware (#311)
H2C was mapped to the "h2d" firmware API key, causing it to check
the H2D firmware page and offer H2D firmware for download. H2C has
its own separate firmware track (01.01.x.x vs H2D's 01.02.x.x).

Changed H2C to use its own "h2c" API key and added the reverse
mapping. Also added missing H2C (O1C) and H2S (O1S) entries to
the printer model ID and 3MF model name maps.
2026-02-10 08:51:44 +01:00
maziggy 53e13ecbd2 Fix H2C nozzle rack showing wrong slots and redesign to compact layout (#300)
The nozzle_info MQTT array contains L/R nozzle heads (IDs 0, 1) and
  rack slots (IDs 16-21). Backend was dumping all entries into nozzle_rack,
  and frontend slice(0,6) grabbed L, R, plus only 4 rack slots — cutting
  off the last position (e.g. the 0.6mm nozzle) and showing the mounted
  nozzle as docked.

  Backend: filter nozzle_rack to id >= 2 (rack-only), sort by ID.
  Frontend: compact single-row layout with bottom accent bars for
  mounted/docked status, wider rack card (flex-[2]), vertically
  centered temp cards.
2026-02-10 08:44:58 +01:00
copilot-swe-agent[bot]andcadtoolbox a3581dc035 Remove redundant CSS properties from email templates
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-10 02:08:03 +00:00
copilot-swe-agent[bot]andcadtoolbox b29436323d Fix email template visibility issues for dark mode compatibility
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-10 02:05:34 +00:00
copilot-swe-agent[bot]andcadtoolbox 3bbd1eb199 Fix email template formatting - convert newlines to br tags and increase header padding
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-10 01:14:41 +00:00
copilot-swe-agent[bot]andcadtoolbox 2b8228b5a8 Address code review feedback: fix regex pattern and XSS vulnerabilities
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-10 00:50:23 +00:00
copilot-swe-agent[bot]andcadtoolbox 3aab9d7052 Fix linting issues in email service and auth routes
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-10 00:49:01 +00:00
copilot-swe-agent[bot]andcadtoolbox 94e01499b7 Use notification templates for welcome and password reset emails
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-10 00:48:09 +00:00
maziggy edf244c469 Add local profiles — import OrcaSlicer presets without Bambu Cloud (#310)
Users who use OrcaSlicer without Bambu Cloud can now import slicer
presets directly into Bambuddy. Supports .orca_filament, .bbscfg,
.bbsflmt, .zip, and .json exports with automatic inheritance resolution
via OrcaSlicer's GitHub base profiles (cached with 7-day TTL).
2026-02-09 17:00:02 +01:00
maziggy 6661bbf866 Add full nozzle rack metrics and per-slot hover cards for H2C printers
Capture 4 additional fields from MQTT nozzle data (max_temp, serial_number,
filament_color, filament_id) and surface them through REST/WebSocket APIs.
Add per-slot hover popover to the NozzleRackCard showing all metrics, filament
color backgrounds on slots, and i18n labels in all 4 locales.
2026-02-09 15:10:49 +01:00
maziggy 48174d3a08 Add H2C nozzle rack support — store and display 6-position tool-changer dock
The H2C printer has a tool-changer with a 6-nozzle rack, but
device.nozzle.info entries beyond index 1 were being dropped due to a
hardcoded 2-nozzle limit. This adds full nozzle rack storage, API
exposure, and a frontend card showing all dock positions.
2026-02-09 09:21:50 +01:00
MartinNYHC 1d0e89f571 Merge branch '0.1.9b' into main 2026-02-09 08:18:44 +01:00
copilot-swe-agent[bot]andcadtoolbox efe574591e Add validation for SMTP username when authentication is enabled
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-08 23:10:07 +00:00
copilot-swe-agent[bot]andcadtoolbox 3231a487c9 Update email settings to match notification provider fields and rename tab to Global Email
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-08 23:03:28 +00:00
Gernot Vormayr 47ed16ae60 Limit maximum TLS version in ftp_server to 1.2
This might fix (#58) getting uploads from the linux version of the
BambuStudio network plugin. Issue observer is connection resets with
larger uploads (somewhere >80k).
2026-02-08 23:52:30 +01:00
copilot-swe-agent[bot]andcadtoolbox 7735e8ab09 Fix import shadowing in email_service.py
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-08 15:57:49 +00:00
copilot-swe-agent[bot]andcadtoolbox 1a6a53d92e Address code review feedback - fix hooks and random usage
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-08 15:34:40 +00:00
copilot-swe-agent[bot]andcadtoolbox 1058f3fd5c Add backend support for advanced authentication
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-08 15:23:38 +00:00
maziggy 3f7d2bf619 Fix virtual printer FTP transfer failure with connection reset (#58)
Large 3MF uploads intermittently failed with [Errno 104] Connection
reset by peer while the 16-byte verify_job always succeeded. The
_handle_data_connection callback returned immediately, letting the
asyncio task complete while cmd_STOR was still reading from the data
connection. The passive port listener also stayed open during transfers.

- Keep _handle_data_connection alive via _transfer_done event so the
  asyncio task holds strong references throughout the transfer
- Close passive port listener after accepting the data connection
- Reject duplicate data connections with a warning log
- Add drain timeout (5s) to MQTT status pushes to prevent blocking
  when the slicer is busy with FTP upload
- Improve error logging with bytes received and exception type
2026-02-08 14:37:50 +01:00
maziggy e073e494c7 Fix H2D Pro wrong nozzle routing causing extrusion motor overload (#245)
H2D Pro firmware interprets use_ams as a nozzle index when sent as
integer (1 = deputy nozzle) instead of boolean. Bambu Studio sends
use_ams: true (boolean) while using integers for calibration fields.
Bambuddy was converting all boolean fields to integers for H2D series,
routing filament to the deputy nozzle instead of main, causing
extrusion motor overload at ~75% print completion.

Keep use_ams as boolean for all printers, matching Bambu Studio format.
2026-02-08 08:18:52 +01:00
MartinNYHC 00d60d4bb8 Merge pull request #295 from bambuman/bug/spoolman-creates-dublicate-spools
bug/spoolman-creates-dublicate-spools
2026-02-08 07:55:07 +01:00
bambuman c04df8ceb9 Add retry logic and connection resilience to Spoolman sync
Implements retry mechanism to handle intermittent network errors when
fetching spools cache for AMS sync operations.

Changes:
- Add retry logic to get_spools() with 3 attempts and 500ms delay
- Configure httpx client with connection pool limits to prevent stale
  connection reuse (max_keepalive_connections=5, keepalive_expiry=30s)
- Recreate client on connection errors (ReadError, RemoteProtocolError)
- Abort sync operations if cache fetch fails after all retries
- Update on_ams_change, sync_single_printer, and sync_all_printers to
  handle cache fetch failures gracefully

This addresses ReadError(ClosedResourceError()) failures that occurred
intermittently when Spoolman closed idle connections or connection
pooling reused stale connections.

Testing:
- Added 4 new unit tests for retry behavior
- All 1018 tests passing
2026-02-07 23:11:27 +02:00
bambuman deab81287f Optimize AMS Spoolman sync performance with spool caching
- Add cached_spools parameter to find_spool_by_tag, find_spools_by_location_prefix, sync_ams_tray, and clear_location_for_removed_spools
- Fetch spools once before loops in on_ams_change, sync_single_printer, and sync_all_printers endpoints
- Cache newly created spools during sync to avoid duplicate API calls
- Add 5 unit tests for caching functionality (all passing)
- Reduce redundant API calls when syncing multiple AMS trays
- Improve sync performance for users with large spool databases
- Maintain backward compatibility with optional cached_spools parameters
2026-02-07 22:29:52 +02:00
MartinNYHC 2cff40f2f1 Merge branch '0.1.9b' into feature/home-assistant-env-vars 2026-02-07 19:55:11 +01:00
bambuman eda1f5a9e7 Home Assistant: add environment variable configuration support
- Add HA_URL and HA_TOKEN environment variables for automatic HA
  integration configuration in HA add-on deployments
- Environment variables always override database settings with
  non-negotiable precedence; database values preserved for fallback
- Auto-enable integration when both env vars are set; partial config
  (one env var) uses database enable state without auto-enabling
- Add centralized get_homeassistant_settings() function following
  Spoolman pattern; replace direct database queries across codebase
- Add ha_url_from_env, ha_token_from_env, ha_env_managed fields to
  AppSettings schema to inform frontend about configuration source
- UI shows read-only fields with lock icons and "(Environment Managed)"
  labels when env-controlled; toggle shows auto-enable badge
- Add comprehensive test coverage: 9 integration + 8 unit tests

Closes #283
2026-02-07 19:01:04 +02:00
maziggy 42fc819efc Add proxy mode for virtual printer (cross-LAN slicer support)
Enable Bambu Studio on a remote network to print through BamBuddy
acting as a TLS-terminating proxy for both MQTT and FTP connections.

- Add TLSProxy base class and FTPTLSProxy with PASV response rewriting,
  EPSV→PASV translation, PROT P/C tracking, and one-shot data proxies
- Add SlicerProxyManager to coordinate per-slicer MQTT + FTP proxy pairs
- Support additional SAN IPs in certificate generation for proxy mode
- Broadcast SSDP on LAN B so slicers discover the proxy as a printer
- Narrow FTP passive port range to 50000-50100 with retry logic
- Expose proxy ports (8883, 9990, 50000-50100) in Dockerfile
- Document passive port range in docker-compose.yml
2026-02-07 15:34:12 +01:00
maziggy 70622e6e53 Add proxy mode for virtual printer (cross-LAN slicer support)
Enable Bambu Studio on a remote network to print through BamBuddy
acting as a TLS-terminating proxy for both MQTT and FTP connections.

- Add TLSProxy base class and FTPTLSProxy with PASV response rewriting,
  EPSV→PASV translation, PROT P/C tracking, and one-shot data proxies
- Add SlicerProxyManager to coordinate per-slicer MQTT + FTP proxy pairs
- Support additional SAN IPs in certificate generation for proxy mode
- Broadcast SSDP on LAN B so slicers discover the proxy as a printer
- Narrow FTP passive port range to 50000-50100 with retry logic
- Expose proxy ports (8883, 9990, 50000-50100) in Dockerfile
- Document passive port range in docker-compose.yml
2026-02-07 15:17:19 +01:00
maziggy 70e7cba5e7 Fix FTP download reporting success on 0-byte files
download_to_file() returned True when retrbinary transferred 0 bytes
without raising an exception. This caused the /cover endpoint to hit
the empty file check and raise HTTP 500 instead of retrying or
returning 404.

Now treats 0-byte downloads as failures, allowing the cover endpoint's
retry logic to work and falling back to 404 if all attempts fail.
2026-02-07 10:04:17 +01:00
maziggy 4b46e443dc Fix critical FTP upload failure and revert dangerous exception narrowing
The CodeQL cleanup in "Housekeeping" (2b11efd) bulk-narrowed except
clauses across 50+ files, breaking FTP uploads on ALL printer models.
ftplib.error_perm (550 errors) is not a subclass of ftplib.error_reply,
so diagnose_storage() CWD failures escaped the handler and prevented
STOR from ever executing — causing 100% upload failure and HTTP 500s
on /api/v1/archives/{id}/reprint and /api/v1/library/files/{id}/print.

FTP fixes:
- Remove diagnose_storage() from upload hot path
- Change all except (OSError, ftplib.error_reply) to
  except (OSError, ftplib.Error) across bambu_ftp.py

Exception handling reverts (9 files):
- Revert narrowed except clauses back to except Exception in route
  handlers and service code where broad catches are intentional
  defensive programming (archive parsing, HTTP clients, 3MF/ZIP
  processing, Home Assistant, firmware checks)
- Keep narrow exceptions only where safe (single-op blocks like
  int(), file.unlink(), socket.close())
- Remove unused XMLParseError imports from archive.py, threemf_tools.py

Closes #287
2026-02-07 09:20:06 +01:00
maziggy aa3482e48b Add printer_model to 18 FTP call sites for A1/A1 Mini, PS1 compatibility
Several FTP operations (file browser, timelapse scan, storage info,
cover download, skip objects, etc.) were missing the printer_model
parameter. Without it, A1/A1 Mini and PS1 printers can't use the prot_p/prot_c
auto-detection and fallback logic, causing FTP failures on these models
when the mode cache isn't already populated.
2026-02-06 16:29:01 +01:00
maziggy 7b90c743c2 Strip explanatory text from nosec comments to silence Bandit warnings
Bandit parses all words after `# nosec BXXX` as test IDs, producing
~35 "not a test name or id" warnings. Trim to just `# nosec BXXX`.
2026-02-06 12:57:37 +01:00
maziggy 598cc699d4 Add CodeQL query suites for zero-finding scans and fix remaining security issues
- Create .codeql/python-bambuddy.qls excluding 14 accepted-risk rule
  categories (all reviewed and documented with justifications)
- Create .codeql/javascript-bambuddy.qls excluding false-positive
  XSS findings (generated coverage file + blob URL in audio src)
- Fix stack trace exposure in updates.py: replace str(e) with generic
  error messages in HTTP responses (2 locations)
- Fix SSRF in homeassistant.py: add _validate_url() with scheme
  validation and metadata-service blocking
- Fix SSRF in tasmota.py: add _validate_ip() blocking loopback and
  link-local addresses
- Add --threads=0 to all CodeQL CLI commands in test_security.sh for
  parallel query evaluation (67s → 43s wall clock)
2026-02-06 12:51:17 +01:00
maziggy 93f416b922 Fix trivial conditionals, commented-out code, and dead variables (CodeQL)
Simplify always-true authEnabled ternary and localSettings truthiness
checks in SettingsPage.tsx. Remove commented-out auth re-setup guard
and its dead _existing_setting/_user_count queries from auth.py.
Add clarifying comments to firmware_check.py api_key logs (model
identifier, not a secret).
2026-02-06 12:32:29 +01:00
maziggy b99536cc33 Remove unused imports, variables, and fix minor CodeQL findings
- Remove 28 unused imports across 22 test files
- Prefix 4 unused local variables with _ in app code
  (archives, bambu_mqtt, main) and remove 1 dead store
- Consolidate import/import-from in test_plate_detection.py
- Fix unreachable statement in test_archive_service.py
- Simplify redundant comparison in timelapse_processor.py

Resolves ~50 CodeQL py/unused-import, py/unused-local-variable,
py/import-and-import-from, py/unreachable-statement, and
py/redundant-comparison findings.
2026-02-06 12:19:17 +01:00
maziggy 5dcabbdda8 Remove 30 redundant function-level imports
These modules were already imported at the top of each file.
Removes re-imports of re, json, zipfile, and logging from
inside functions in archive.py, library.py, main.py,
printers.py, support.py, and test_library_api.py.

Resolves all 30 CodeQL py/repeated-import findings.
2026-02-06 12:06:51 +01:00
maziggy 5b0a985da2 Add explanatory comments to 265 empty except blocks
CodeQL flags except blocks where `pass` has no comment explaining
why the exception is silently ignored (py/empty-except rule).

Added context-specific comments to all 265 instances across 31 files:
- database.py (~112): ALTER TABLE migrations — "Already applied"
- archive/library/3MF parsing (~64): "Skip unparseable metadata"
- virtual_printer network cleanup (~32): "Best-effort socket cleanup"
- discovery/SSDP (~13): "SO_REUSEPORT not available" / socket cleanup
- bambu_ftp/mqtt (~13): FTP cleanup, JSON decode, signal parsing
- remaining routes/services (~31): context-specific comments
2026-02-06 11:58:38 +01:00
maziggy a0133fb43b Fix safe security findings: hashlib, log injection, broad excepts, bandit suppressions
- Add usedforsecurity=False to MD5 (AMS fingerprint) and SHA1 (git blob
  hash) calls to silence Bandit B303 / CodeQL weak-crypto findings
- Convert ~996 f-string logging calls to parameterized %s-style across
  55 files to prevent log injection (Bandit G201 / CodeQL log-injection)
- Narrow ~199 broad except Exception blocks to specific types:
  OperationalError for DB migrations, OSError for network/file cleanup,
  (OSError, ftplib.error_reply) for FTP, and targeted tuples for
  ZIP/XML/JSON parsing — 36 intentionally left broad (mixed async,
  re-raise patterns)
- Add # nosec comments to 9 known-safe lines (0.0.0.0 virtual printer
  binds, ftplib imports) and exclude backend/tests/ from bandit scan
- Bandit now reports 0 medium/high findings
2026-02-06 11:45:12 +01:00
maziggy 53bd4fadb3 Fix safe security findings: hashlib, log injection, broad excepts
- Add usedforsecurity=False to MD5 (AMS fingerprint) and SHA1 (git blob
  hash) calls to silence Bandit B303 / CodeQL weak-crypto findings
- Convert ~996 f-string logging calls to parameterized %s-style across
  55 files to prevent log injection (Bandit G201 / CodeQL log-injection)
- Narrow ~199 broad except Exception blocks to specific types:
  OperationalError for DB migrations, OSError for network/file cleanup,
  (OSError, ftplib.error_reply) for FTP, and targeted tuples for
  ZIP/XML/JSON parsing — 36 intentionally left broad (mixed async,
  re-raise patterns)
2026-02-06 11:37:59 +01:00
maziggyandClaude Opus 4.6 91662d9c5d Add usedforsecurity=False to non-security hashlib calls
MD5 in bambu_mqtt.py is used for AMS tray change detection fingerprinting,
and SHA1 in github_backup.py matches Git's blob hash format. Neither is
used for security purposes, so mark them explicitly to satisfy Bandit B303
and CodeQL py/weak-cryptographic-algorithm findings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 11:15:26 +01:00
maziggy dc82b5ff2a Refactor Spoolman per-filament tracking (PR #277 follow-up)
Extract Spoolman tracking from main.py into dedicated service module,
DRY up repeated helpers, add i18n for new settings UI, and add tests.

- Move ~460 lines from main.py to services/spoolman_tracking.py
- Extract _resolve_spool_tag, _resolve_global_tray_id, build_ams_tray_lookup helpers
- Replace fragile tuple return in get_spoolman_settings() with dict
- Wire 4 new UI strings through i18n (en/de/ja)
- Add 42 backend unit tests (spoolman tracking helpers + 3MF parsing)
- Add 6 frontend tests for weight sync and partial usage toggles
- Update CHANGELOG, wiki, and website docs

Closes PR #277
2026-02-06 10:03:27 +01:00
MartinNYHC 0dcb154ae3 Merge branch '0.1.8b' into feature/accurate-usage-tracking 2026-02-06 09:21:44 +01:00
maziggy b4285913a9 Remove 24-hour queue item expiration logic
Queue items were being marked as "expired" if older than 24 hours,
which breaks legitimate use cases like weekend print queues or
printers that are offline for extended periods.
2026-02-06 08:32:28 +01:00
BambuMan 0a39b12064 Merge branch 'maziggy:main' into feature/accurate-usage-tracking 2026-02-05 19:53:52 +02:00