Commit Graph
375 Commits
Author SHA1 Message Date
Dennis bf75cd2527 Remove unused import statement for sqlalchemy in main.py 2026-02-04 14:36:32 +01:00
Dennis 84f1347bd0 Reorder import statement for jwt in main.py 2026-02-04 14:36:32 +01:00
maziggy 84d2517aa1 Fixed backup permissions 2026-02-03 14:04:36 +01:00
maziggy 691b7e262a Fix for Information exposure through an exception #72 2026-02-03 13:36:22 +01:00
maziggy 37b73b8868 Sync 2026-02-03 13:02:36 +01:00
maziggy 8b2bdebb3f Sync 2026-02-03 12:42:55 +01:00
maziggy 89b19cbe4f Sync 2026-02-03 12:40:01 +01:00
maziggy 9787400935 Sync 2026-02-03 12:27:36 +01:00
maziggy a0f3b02287 Bumped version 2026-02-03 11:41:31 +01:00
maziggy 583c374f01 Add Virtual Printer Proxy Mode for remote printing
Introduces a new "Proxy Mode" for the Virtual Printer that enables
remote printing from anywhere in the world without VPN, port forwarding,
or Bambu Cloud dependency.

Bambuddy acts as a TLS relay between a remote slicer (Bambu Studio/
OrcaSlicer) and the local Bambu Lab printer:

  Remote Slicer → Internet → Bambuddy Server → Local Network → Printer

The slicer connects to Bambuddy using the real printer's serial number
and access code. Bambuddy authenticates and relays all FTP (file transfer)
and MQTT (commands/status) traffic with end-to-end TLS encryption.

- No port forwarding required - printer stays safely on local network
- No VPN needed - connect from coffee shops, hotels, work, anywhere
- No Bambu Cloud dependency - fully self-hosted solution
- End-to-end TLS encryption on FTP (port 9990) and MQTT (port 8883)
- Works with Bambu Studio and OrcaSlicer
- Uses real printer credentials for authentication
- Automatic printer selection from connected printers

- Add SlicerProxyManager class for TLS relay (tcp_proxy.py)
  - TLS termination with auto-generated certificates
  - Concurrent FTP and MQTT proxy servers
  - Connection lifecycle management with proper cleanup
- Extend VirtualPrinterManager with proxy mode support
  - New 'proxy' mode alongside archive/review/queue modes
  - Target printer selection and credential management
- Add proxy configuration endpoints to settings API
- Add permission checks for proxy endpoints

- Add Proxy Mode card to Virtual Printer settings
- Target printer dropdown for proxy destination
- Real-time proxy status display (ports, target, running state)
- Full i18n support (English, German)

- Add network architecture diagram
- Add proxy mode section to README
- Add comprehensive guide to wiki
- Add prominent feature section to website

- Backend unit tests for SlicerProxyManager
- Backend unit tests for proxy mode configuration
- Frontend tests for proxy mode UI components

Closes #207 #170
2026-02-03 11:02:13 +01:00
maziggy 99fa902b64 Allow multiple Home Assistant entities per printer (fixes #214)
Both frontend and backend were blocking printers that already had any
smart plug linked, preventing users from adding multiple HA entities
to the same printer.

Changes:
- Frontend: Only filter out printers with existing Tasmota plugs
- Backend: Only check for duplicate Tasmota plugs on create/update
- HA entities (switches, scripts, lights, etc.) can now be linked
  multiple times to the same printer for different automations
- Tasmota plugs remain limited to one per printer (physical device)
- Restored "Show on Printer Card" toggle for HA entities
- Fixed printer card only showing script.* entities; now shows all
  HA entities with the toggle enabled
- HA entities now default to auto_on=False and auto_off=False
- Printer cards now update immediately when HA entities change

Closes #214
2026-02-03 09:13:13 +01:00
maziggy a82f9278d2 Add authentication to 200+ API endpoints (CVE-2026-25505)
Security fix for critical vulnerability (CVSS 9.8) where API endpoints
were accessible without authentication when auth was enabled.

Changes:
- Add RequirePermissionIfAuthEnabled() to all unprotected route files:
  archives, projects, settings, api_keys, groups, cloud, github_backup,
  support, notifications, notification_templates, maintenance, filaments,
  external_links, smart_plugs, discovery, firmware, kprofiles, camera,
  ams_history, pending_uploads, updates, spoolman, system, print_queue,
  printers
- Keep image-serving endpoints (thumbnails, timelapse, photos, camera
  streams, icons) unauthenticated since <img> tags cannot send headers
- Add backend integration tests for endpoint auth enforcement
- Add frontend tests for ownership-based permissions (canModify)

Fixes: CVE-2026-25505
2026-02-03 09:13:00 +01:00
maziggy 572dbf393e Fix 500 error on GET /archives/{id} endpoint
Load project relationship in ArchiveService.get_archive() alongside
created_by. Async SQLAlchemy doesn't support lazy loading, so project
must be eagerly loaded for archive_to_response() to access project.name.
2026-02-03 09:13:00 +01:00
maziggy 6431a86e2f Fix monthly comparison calculation ignoring quantity multiplier (Issue #229)
The filament statistics were under-reporting totals because the quantity
field was not being multiplied with filament_used_grams. When users
printed multiple items (quantity > 1), only the base filament amount
was counted instead of the total.

Closes #229
2026-02-03 09:12:43 +01:00
maziggy bb61a1dbef Add TOTP authenticator support for Bambu Cloud login (fixes #182)
TOTP (Two-Factor Authentication):
- Detect TOTP vs email verification from Bambu API loginType response
- Use dedicated TFA endpoint on bambulab.com (not api.bambulab.com)
- Include browser-like headers to bypass Cloudflare protection
- Extract token from JSON response or cookies
- Frontend shows appropriate messages for each verification type
- Added i18n translations for TOTP UI (en, de, ja)

Closes #182
2026-02-03 09:12:31 +01:00
maziggy 38d99143c7 Virtual Printer: TLS proxy with real printer serial
Proxy mode changes:
  - Replace transparent TCP proxy with TLS-terminating proxy
  - Slicer connects to Bambuddy cert, Bambuddy connects to printer
  - Use real printer's serial number for SSDP and certificate
  - This ensures MQTT topic subscriptions match the real printer

  The proxy now:
  1. Accepts TLS from slicer using Bambuddy's certificate
  2. Opens TLS connection to real printer
  3. Forwards decrypted data bidirectionally

  Also: Complete i18n localization for VirtualPrinterSettings component
2026-02-02 15:55:55 +01:00
maziggy be18ebb36c Fix P2S printer support - disable vibration_cali and fix FTP SSL
Author: deathly1987 <andre@welker.one>
2026-02-02 14:09:40 +01:00
maziggy 7eb6058928 Spoolman: Show "Open in Spoolman" for linked spools (Issue #210)
When a spool is already linked in Spoolman, the FilamentHoverCard now shows
"Open in Spoolman" button instead of "Link to Spoolman". This allows users
to quickly navigate to the spool's page in Spoolman for editing.

Changes:
- Add GET /api/v1/spoolman/spools/linked endpoint returning tag->spool_id map
- FilamentHoverCard shows "Open in Spoolman" when linkedSpoolId is set
- "Link to Spoolman" only shows when spool is not linked
- Fix unlinked spools detection to strip JSON quotes from empty tags
- Add toast notifications for link success/failure
- Invalidate linked-spools query after linking
- Add backend tests for linked spools endpoint
- Add frontend tests for LinkSpoolModal

Closes #210
2026-02-02 09:23:50 +01:00
maziggy db68dda1f5 Document intentional JWT secret storage (CodeQL Alert #69)
Add explanatory comment for CodeQL alert about clear-text storage
of JWT secret. This is intentional and secure:
- JWT secrets must be readable by the application
- File permissions set to 0600 (owner read/write only)
- Standard practice for self-hosted apps (same as .env files)

The alert should be dismissed in GitHub Security tab as "Won't fix".
2026-02-02 08:19:51 +01:00
maziggy 70f5b6ae98 Bumped version 2026-02-02 08:16:33 +01:00
maziggy 0fa180a5ee Bumped version 2026-02-02 08:04:54 +01:00
maziggy e4e37fb99e Issue #224: File Manager Permissions
The File Manager (Library) backend had no permission enforcement - endpoints were returning data to any authenticated user regardless of their group permissions.

Closes #224
2026-02-02 08:01:42 +01:00
maziggy 018a744475 Location filter for queue and auth fixes (Issue #220)
Features:
- Add location filter for "Any {Model}" queue assignments
- Queue items can target a specific location (e.g., "Any X1C in Workshop")
- Location dropdown filter on Queue page to view jobs by location
- Scheduler considers location when assigning model-based jobs

Closes #220
2026-02-02 07:39:58 +01:00
maziggy c31f296888 Fix critical security vulnerabilities (GHSA-gc24-px2r-5qmf)
## Summary
  Address two critical security issues reported via GitHub Security Advisory:
  1. Hardcoded JWT secret key allowing token forgery
  2. Missing authentication on 77+ API endpoints

  ## Changes

  ### JWT Secret Key (backend/app/core/auth.py)
  - Remove hardcoded secret "bambuddy-secret-key-change-in-production"
  - Load secret from JWT_SECRET_KEY environment variable (recommended)
  - Fall back to .jwt_secret file in data directory (auto-generated)
  - Generate cryptographically secure 64-byte random secret if neither exists
  - File is created with 0600 permissions for security

  ### API Authentication Middleware (backend/app/main.py)
  - Add HTTP middleware that enforces auth on ALL /api/ routes
  - When auth is enabled, every API request requires valid JWT or API key
  - Only exempt routes that must be public:
    - /api/v1/auth/status (check if auth enabled)
    - /api/v1/auth/login (login endpoint)
    - /api/v1/updates/version (version check)
    - /api/v1/ws/* (WebSockets handle own auth)

  ### Test Updates
  - backend/tests/conftest.py: Patch middleware's async_session for tests
  - backend/tests/integration/test_ownership_permissions.py: Add missing
    auth headers to requests that now require authentication

  ## Migration Notes
  - Existing JWT tokens will be invalidated (users must re-login)
  - Set JWT_SECRET_KEY env var in production for token persistence across restarts
  - No database changes required

  Fixes: GHSA-gc24-px2r-5qmf
  Security: CWE-306 (Missing Authentication), CWE-321 (Hardcoded Crypto Key)

Closes GHSA-gc24-px2r-5qmf
2026-02-02 06:51:55 +01:00
maziggy 234693a306 Fix external spool ams_mapping2 slot_id (Issue #213)
The ams_mapping2 format was incorrectly using the tray_id (254/255) as
the slot_id for external spools. The printer expects slot_id to be the
actual slot index (0 for main nozzle, 1 for deputy nozzle), not the
tray_id value.

Before: {"ams_id": 255, "slot_id": 254}  <- invalid slot index
After:  {"ams_id": 255, "slot_id": 0}    <- correct slot index

This caused prints using external spool to fail immediately with error
code 07FF_8007.

Closes #213
2026-02-01 16:29:06 +01:00
maziggy 4dad18a331 Fixed CodeQL Alert #68: Stack trace exposure in archives.py 2026-02-01 16:20:07 +01:00
maziggy dce9c8bc06 Fix filename matching for files with spaces (Issue #218)
Bambu Studio converts spaces to underscores when saving files to the
printer, but MQTT reports the original name with spaces. This caused
FTP downloads to fail with "550 Failed to open file" because we were
searching for "Battery Storage_giesela.gcode.3mf" but the actual file
was "Battery_Storage_giesela.gcode.3mf".

Changes:
- Add underscore variants to direct download path attempts
- Normalize spaces/underscores in fallback directory search
- Apply fix to archive download, cover extraction, and objects reload

Closes #218
2026-02-01 16:08:49 +01:00
maziggyandClaude Opus 4.5 4b2ea2d2c2 Fix P2S FTP upload failure - pass skip_session_reuse to ImplicitFTP_TLS (Issue #218)
The fix for A1/P1S FTP uploads (commit 82a6025) was accidentally broken in
commit 9969005 which removed the skip_session_reuse parameter from the
ImplicitFTP_TLS constructor. This caused P2S (and other models in
SKIP_SESSION_REUSE_MODELS) to still use SSL on the data channel, resulting
in "426 Failure reading network stream" errors.

The fix was implemented in commit b96ecfa on test/issue_174 branch but
never merged to main. This cherry-picks that fix.

Also includes:
- Storage diagnostics for debugging upload issues
- Better FTP error logging with specific error codes (553, 550, 552)
- Improved error messages in print scheduler

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 15:15:18 +01:00
maziggy 2d445badac Fix printer deletion freeze and allow multiple smart plugs per printer (Issue #214)
Bug 1: Delete printer was not actually deleting archives when
delete_archives=True (default). The if-condition was inverted, causing
archives to remain and potentially causing FK constraint issues.

Bug 2: SmartPlug.printer_id had unique=True constraint, preventing
multiple HA scripts from being linked to the same printer. Removed the
constraint to allow multiple plugs/scripts per printer (matching
feature/176 behavior).

Closes #214
2026-02-01 14:39:04 +01:00
maziggy 0b3df17920 Sanitize printer serial numbers in support bundle logs (Issue #216)
The support bundle states that printer serial numbers are NOT collected,
but they were appearing in debug logs. Added regex to sanitize Bambu Lab
serial numbers (00M/01D/01S/01P/03W prefix + alphanumeric) while keeping
the prefix for debugging context.

Example: [01D00A12345678] -> [01D[SERIAL]]

Closes #216
2026-02-01 14:26:56 +01:00
maziggy 16fadba765 Fix missing sliced_for_model migration - for real this time (Issue #211)
PR #215 claimed to fix this but the actual ALTER TABLE migration was
not included. Users upgrading from 0.1.6b11 to 0.1.6 still see:
"no such column: print_archives.sliced_for_model"

This commit adds the actual migration that was missing.

Closes #211
2026-02-01 14:03:42 +01:00
maziggy 60bb29be2f Fix external spool AMS mapping causing "Failed to get AMS mapping table" (Issue #213)
When printing with external spool holder (no AMS connected), the printer
reported error [0700-8012] "Failed to get AMS mapping table".

Root cause: The ams_mapping2 calculation for external spool (tray_id=254)
was incorrectly computing ams_id=63, slot_id=2 instead of the required
ams_id=255, slot_id=254.

The fix adds special handling for external spool tray IDs (254 for main
nozzle, 255 for deputy nozzle) which use ams_id=255 with slot_id matching
the tray_id.

Fixes #213
2026-02-01 13:57:21 +01:00
maziggy ade4792eac Add separate permission for AMS RFID re-read (Issue #204)
- Add new `printers:ams_rfid` permission for re-reading AMS RFID tags
- Allows granting RFID re-read access without full printer control
- Operators group includes this permission by default
- Previously used `printers:control` which grants broader access
- Permission available in Settings > Users > Group Editor

Closes #204
2026-02-01 11:39:37 +01:00
maziggy d715132a84 Implement ownership-based permissions (Issue #205)
Backend:
- Split update/delete permissions into *_own and *_all variants:
  - queue:update_own/all, queue:delete_own/all
  - archives:update_own/all, archives:delete_own/all, archives:reprint_own/all
  - library:update_own/all, library:delete_own/all
- Add require_ownership_permission dependency factory in auth.py
- Enforce ownership checks on all relevant API endpoints:
  - archives.py: PATCH, DELETE, POST /reprint
  - print_queue.py: PATCH, DELETE, POST /cancel, PATCH /bulk
  - library.py: PUT /files, DELETE /files, POST /bulk-delete, DELETE /folders
- Add user items count endpoint: GET /users/{id}/items-count
- Add delete_items parameter to DELETE /users/{id}
- Explicitly set created_by_id to NULL on user deletion for DB portability
- Add permission migration for existing groups in database.py
- Add require_permission_if_auth_enabled for folder delete

Frontend:
- Add canModify helper to AuthContext for ownership-based checks
- Update ArchivesPage: use canModify for edit/delete/reprint buttons
- Update QueuePage: use canModify for edit/delete/cancel buttons
- Update FileManagerPage: use canModify for edit/delete buttons
- Update SettingsPage: add user deletion modal with item handling options
- Update StatsPage: use archives:update_all for recalculate costs
- Update Permission type with new ownership permissions
- Add getUserItemsCount and update deleteUser API methods

Tests:
- Add test_ownership_permissions.py with 28 comprehensive tests
- Test admin *_all permissions, operator *_own permissions
- Test bulk operations skip non-owned items
- Test auth disabled allows all operations
- Test user deletion with/without items

Closes #205
2026-02-01 11:29:17 +01:00
maziggy 81cc8412ac Add user tracking for prints, archives, library files, and queue (Issue #206)
Track and display who performs key actions in Bambuddy:
- Archives: who uploaded each archive file
- Library: who uploaded each file in File Manager
- Queue: who added each print job to the queue
- Printers: who started the current print (reprint tracking)

Backend changes:
- Add created_by_id column to print_archives, library_files, print_queue tables
- Add database migrations for new columns (auto-run on startup)
- Update archive, library, and queue routes to capture current user
- Add current-print-user endpoint for printer reprint tracking
- Track reprint user in PrinterManager in-memory state
- Fix file uploads not sending auth headers (FormData requires explicit headers)

Frontend changes:
- Display username on archive cards, library files, queue items
- Show "Started by" on printer cards during active prints
- Add auth headers to all 12 FormData upload functions
- Update TypeScript types for user tracking fields

Tests:
- Add unit tests for PrinterManager user tracking methods (7 tests)
- Add integration tests for current-print-user endpoint (3 tests)
- Add integration tests for library file user tracking (3 tests)

Works when authentication is enabled; gracefully hidden when disabled.

Closes #206
2026-02-01 10:26:11 +01:00
maziggy 9bd12df6bf Changed tests for new backup module 2026-02-01 09:18:31 +01:00
maziggy 40d285db2e Add relative path storage for library files to fix backup portability
Library files now store paths relative to base_dir instead of absolute
  paths. This ensures thumbnails and files work correctly after restoring
  a backup on a different system or with a different data directory.

  Changes:
  - Add to_relative_path() and to_absolute_path() helper functions
  - Update file upload, ZIP extraction, and STL thumbnail generation
    to store relative paths
  - Update download, thumbnail, gcode, and delete endpoints to resolve
    relative paths when accessing files
  - Add database migration to convert existing absolute paths to relative

  Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

  The code is ready for testing. After pushing to the remote host:

  1. The migration will run automatically on startup, converting any existing absolute paths
  2. New files will be stored with relative paths
  3. Thumbnails should display correctly after backup/restore
2026-02-01 08:58:28 +01:00
maziggy e1ff8f19e7 Simplify backup/restore with complete database + files ZIP approach
Replace the complex JSON-based backup system (~2000 lines) with a simple
  approach that copies the SQLite database and all data directories into a
  single ZIP file.

  Backend changes:
  - Add close_all_connections() and reinitialize_database() helpers to database.py
  - New GET /backup endpoint: creates complete ZIP with bambuddy.db and all
    data directories (archive, virtual_printer, plate_calibration, icons, projects)
  - New POST /restore endpoint: extracts ZIP, replaces database and directories,
    requires restart after restore
  - Move legacy endpoints to /backup-legacy and /restore-legacy for transition

  Frontend changes:
  - Simplify api.exportBackup() - no longer takes category parameters
  - Simplify api.importBackup() - no longer takes overwrite parameter
  - Remove BackupModal and RestoreModal components from GitHubBackupSettings
  - Add simple Download/Restore buttons with inline logic
  - Add blocking modal overlay during backup/restore operations
  - Add beforeunload handler to prevent accidental navigation
  - Show operation status messages during backup/restore

  Benefits:
  - ~100 lines vs ~2000 lines of backup/restore code
  - Complete by definition - SQLite database contains ALL data
  - No code changes needed when schema changes
  - No ID remapping required - IDs stay the same
  - Faster - file copy vs querying all tables
2026-02-01 08:35:49 +01:00
maziggy 304157133c Bumped version 2026-01-31 19:09:56 +01:00
maziggy 7d1f98e407 Missing Model Imports (Fixed):
1. ams_history - AMS sensor history table
  2. pending_upload - Virtual printer pending uploads table
  3. slot_preset - AMS slot preset mappings table

  Missing Column Migrations (Added earlier in session):
  1. print_queue.target_model - Model-based queue assignment
  2. print_queue.required_filament_types - Filament type requirements
  3. print_queue.waiting_reason - Why job is waiting
  4. printers.nozzle_count - Dual-extruder detection
  5. printers.print_hours_offset - Baseline hours adjustment
  6. notification_providers.on_queue_job_added - Queue job added notification
  7. notification_providers.on_queue_job_assigned - Queue job assigned notification
  8. notification_providers.on_queue_job_started - Queue job started notification
  9. notification_providers.on_queue_job_waiting - Queue job waiting notification
  10. notification_providers.on_queue_job_skipped - Queue job skipped notification
  11. notification_providers.on_queue_job_failed - Queue job failed notification
  12. notification_providers.on_queue_completed - Queue completed notification

  Tables verified as OK (no migrations needed):
  - api_keys - No new columns since v0.1.5
  - external_links - No new columns since v0.1.5
  - library_files/folders - New in v0.1.6, created fresh
  - github_backup_config/logs - New in v0.1.6, created fresh
  - project_bom_items - New in v0.1.6, created fresh
  - groups/user_groups - New in v0.1.6, created fresh
2026-01-31 18:15:38 +01:00
maziggyandClaude Opus 4.5 0a9bca2239 Add missing migrations for printer nozzle_count and print_hours_offset
These columns were added in 0.1.6 beta but migrations were missing:
- nozzle_count: Integer DEFAULT 1 (for dual-extruder detection)
- print_hours_offset: Float DEFAULT 0.0 (baseline hours adjustment)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 17:46:17 +01:00
maziggyandClaude Opus 4.5 7e88092d61 Add missing migration for model-based queue columns
Add migration for target_model, required_filament_types, and waiting_reason
columns in print_queue table. These columns were added to the model for the
model-based queue assignment feature but the migration was missing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 17:34:06 +01:00
maziggyandClaude Opus 4.5 85c180909b Break SSRF taint chain by reconstructing URLs from validated components
- Add _sanitize_camera_url() that returns reconstructed URL from
  validated and parsed components, breaking CodeQL's taint tracking
- Update _capture_mjpeg_frame, _capture_snapshot, _stream_mjpeg to
  use sanitized URLs instead of original user input
- Keep _validate_camera_url as legacy wrapper for backwards compat

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 16:53:37 +01:00
maziggyandClaude Opus 4.5 2960261aa9 Add SSRF mitigation for external camera URLs
Block access to cloud metadata services and dangerous destinations:
- AWS/GCP/Azure metadata endpoint (169.254.169.254)
- GCP internal metadata hostnames
- localhost and loopback addresses
- All link-local addresses (169.254.x.x)

Local network IPs (192.168.x.x, 10.x.x.x) are still allowed since
cameras are typically on the same LAN as the server.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 16:49:12 +01:00
maziggyandClaude Opus 4.5 57e88044e9 Fix CodeQL security warnings
- Path traversal: Convert device number to integer to break taint chain,
  use strict /dev/videoN validation with range limit
- SSRF: Add documentation explaining intentional SSRF for user-configured
  external camera URLs, add lgtm suppression comments
- Info exposure: Don't expose exception messages in plate calibration
  errors, only expose error type name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 16:45:13 +01:00
maziggy d713577863 Fixed CodeQL errors 2026-01-31 16:35:10 +01:00
MartinNYHC be7b3f99a2 Merge branch '0.1.6-final' into feature/192 2026-01-31 15:36:17 +01:00
MartinNYHC 391214be79 Merge branch '0.1.6-final' into feature/auth_details 2026-01-31 15:15:39 +01:00
maziggy 0664c96cbf Misc merge fixes 2026-01-31 15:09:23 +01:00
maziggyandClaude Opus 4.5 a965afa6cb Merge branch '0.1.6-final' into feature/173
Merged MQTT smart plug support with latest 0.1.6-final features.
Kept MQTT plug functionality (separate topics, multipliers, etc.)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 15:00:12 +01:00