Fixed CodeQL errors

This commit is contained in:
maziggy
2026-01-31 16:35:10 +01:00
parent c454cad075
commit d713577863
4 changed files with 393 additions and 10 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
All notable changes to Bambuddy will be documented in this file.
## [0.1.6-final] - Not released
## [0.1.6-final] - 2026-01-31
### New Features
- **Group-Based Permissions** - Granular access control with user groups:
+318
View File
@@ -0,0 +1,318 @@
# Bambuddy v0.1.6 - Final Release
**Release Date:** January 31, 2026
After 11 beta releases and extensive community testing, we're excited to announce **Bambuddy 0.1.6-final** - our biggest release yet! This release brings optional authentication, build plate detection, external camera support, model-based queue scheduling, and much more.
---
## Highlights
### Optional Authentication & User Management
Secure your Bambuddy instance for the first time:
- Enable/disable authentication via Settings
- **Role-based access**: Admin (full access) and User (prints only) roles
- **Group-based permissions**: 50+ granular permissions with custom groups
- JWT-based authentication with user management UI
- Users can change their own password from the sidebar
### Build Plate Empty Detection
Never start a print with objects on the bed again:
- Per-printer toggle for plate detection
- Multi-reference calibration (up to 5 plate types)
- Automatic print pause when objects detected
- Push notifications and WebSocket alerts
- ROI calibration for precise detection area
### External & USB Camera Support
Use any camera with your printers:
- **External cameras**: MJPEG, RTSP, HTTP snapshot support
- **USB cameras**: V4L2 webcam support on Linux
- Layer-based timelapse with external cameras
- Finish photo capture from external sources
### Model-Based Queue Assignment
Perfect for print farms:
- Queue items to "Any X1C", "Any P1S", etc.
- Auto-assigns to available printer when ready
- Automatic filament validation and AMS mapping
- Matches required filaments to loaded spools
### GitHub Profile Backup
Automated backup of your settings to GitHub:
- Schedule hourly, daily, or weekly backups
- Backs up K-profiles, cloud profiles, and app settings
- Skip unchanged commits (only commit when data changes)
- Backup history log with commit links
### Prometheus Metrics
Export printer telemetry for external monitoring:
- Endpoint: `GET /api/v1/metrics`
- Printer temps, fans, WiFi, print progress
- Ready for Grafana dashboards
- Optional bearer token authentication
---
## New Features
### Authentication & Security
- **Optional Authentication** - Secure your Bambuddy instance with JWT-based user authentication
- **Group-Based Permissions** - 50+ granular permissions with custom groups (Administrators, Operators, Viewers)
- **Change Password** - Users can update their own password from sidebar
- **API Keys** - API key authentication with granular permissions
### Virtual Printer
- **Virtual Printer** - Emulates a Bambu Lab printer on your network for Bambu Studio/Orca Slicer
- **Virtual Printer Queue Mode** - Auto-archive and queue prints from slicer
- **Virtual Printer Model Selection** - Choose which printer model to emulate
- **TLS 1.3 Encryption** - Secure MQTT + FTPS with auto-generated certificates
### Print Queue & Scheduling
- **Model-Based Queue Assignment** - Queue to "Any X1C", "Any P1S" with auto filament matching
- **Multi-Printer Selection** - Send prints to multiple printers at once
- **Per-Printer AMS Mapping** - Configure filament mapping individually per printer
- **Queue Bulk Edit** - Select and edit multiple queue items at once
- **Queue Only Mode** - Stage prints without auto-start, release when ready
- **Unassigned Queue Items** - Queue items without assigned printer
- **Add to Queue from File Manager** - Queue sliced files directly from library
- **Print Queue Plate Selection** - Full print configuration in queue modal
- **Deferred Archive Creation** - Archives created when prints start, not when queued
### Smart Plugs & Automation
- **MQTT Smart Plug Support** - Monitor energy from Zigbee2MQTT, Shelly, Tasmota
- **Home Assistant Integration** - Control any HA switch/light as a smart plug
- **HA Energy Sensors** - Use separate sensor entities for power monitoring
- **Tasmota Discovery** - Auto-discover Tasmota devices on network
- **Switchbar Widget** - Quick power toggle in sidebar
- **Tasmota Admin Link** - Quick access to plug web interface
### Camera & Streaming
- **External Camera Support** - MJPEG, RTSP, HTTP snapshot cameras
- **USB Camera Support** - V4L2 webcam support on Linux
- **Build Plate Empty Detection** - AI-powered detection with multi-reference calibration
- **OBS Streaming Overlay** - Embeddable page at `/overlay/:printerId`
- **Camera Zoom & Fullscreen** - 100%-400% zoom with pan support
- **Multiple Embedded Viewers** - Open multiple camera streams simultaneously
- **Camera View Mode** - Choose between new window or embedded overlay
- **Layer-Based Timelapse** - External camera timelapse on layer change
- **Finish Photo in Notifications** - `{finish_photo_url}` template variable
### File Manager
- **STL Thumbnail Generation** - Auto-generate 3D previews for STL files
- **ZIP File Support** - Upload and extract ZIP files directly
- **Create Folder from ZIP** - Auto-create folder named after ZIP file
- **File Manager Sorting** - Sort by name, size, or date
- **File Manager Rename** - Rename files and folders directly
- **File Manager Print Button** - Print directly from selection toolbar
- **Resizable Sidebar** - Drag to adjust width (200-500px)
- **Text Wrap Toggle** - Wrap long folder names instead of truncating
- **Mobile Accessibility** - Touch-friendly with always-visible menus
### Archives & Projects
- **Multi-Plate Selection** - Select which plate to print from multi-plate 3MF
- **Archive Plate Browsing** - Navigate plate thumbnails in archive cards
- **External Links** - Link archives to Printables, Thingiverse, etc.
- **Fusion 360 Attachments** - Attach F3D design files to archives
- **Project Import/Export** - Export/import projects as ZIP with all files
- **BOM Item Editing** - Edit Bill of Materials items after creation
- **Bulk Project Assignment** - Assign multiple archives to project at once
- **Project Parts Tracking** - Track parts separately from plates
- **Tag Management** - Create, edit, and apply tags to archives
- **Archive Comparison** - Compare 2-5 archives side-by-side
- **AMS Filament Preview** - Preview filament colors in archive cards
### Printer Controls
- **Printer Controls** - Stop and Pause/Resume buttons with confirmation
- **Skip Objects** - Skip individual objects without canceling print
- **Chamber Light Control** - Light toggle button on printer cards
- **Resizable Printer Cards** - Four sizes (S/M/L/XL)
- **H2D Pro Support** - Full support for H2D Pro printer model
### AMS & Filament
- **AMS Color Mapping** - Manual slot selection with auto-matching
- **Expandable Color Picker** - 32 colors in configurable palette
- **AMS Slot RFID Re-read** - Re-read filament info via hover menu
- **Print Options in Modals** - Bed leveling, flow cal, vibration cal, timelapse toggles
### Backup & Monitoring
- **GitHub Profile Backup** - Scheduled backup to GitHub repository
- **Prometheus Metrics** - Export telemetry for Grafana
- **MQTT Publishing** - Publish events to external MQTT brokers
- **Application Log Viewer** - Real-time log viewing with filters
- **Support Bundle** - Debug logging with ZIP generation
- **Comprehensive Backup/Restore** - All settings, users, groups included
### Notifications
- **HMS Error Notifications** - 853 error codes translated to human-readable messages
- **Plate Not Empty Notification** - Dedicated category for plate detection
- **Daily Digest** - Consolidated daily notification summary
- **Notification Templates** - Customizable message templates
- **Slack/Mattermost Format** - Proper payload format support
### Statistics & Dashboard
- **Failure Analysis Widget** - Failure rate with correlations and trends
- **Statistics Improvements** - Size-aware responsive widgets
- **Recalculate Costs** - Button to recalculate all archive costs
- **Time Format Setting** - Configurable date/time format
- **Print Quantity Tracking** - Track items per print for progress
### Other Improvements
- **Firmware Update Helper** - Check versions against Bambu Lab servers
- **Disable Firmware Checks** - Toggle to prevent update checks
- **Printer Discovery** - Docker subnet scanning, model mapping
- **FTP Reliability** - Configurable retry with SSL fixes
- **Pre-built Docker Images** - Pull from GitHub Container Registry
- **One-Shot Install Scripts** - Simple `curl | bash` installation
- **Mobile PWA** - Full mobile support with touch gestures
- **Timelapse Editor** - Trim, speed adjustment, music overlay
- **Sidebar Badge Indicators** - Queue and upload counts
---
## Bug Fixes
### Print Queue & Scheduling
- **Home Assistant Auto-On for Queued Prints** - Fixed smart plug not turning on for queue-started prints (Issue #200)
- **AMS Mapping for Model-Based Queue** - Fixed "Any [Model]" queue jobs failing at filament loading (Issue #192)
- **Queue prints on A1** - Fixed "MicroSD Card read/write exception error" when starting prints from queue
- **Multi-Plate Queue Thumbnails** - Queue now shows correct plate thumbnail (Issue #166)
- **Queue items with library files** - Fixed 500 errors when listing/updating queue items from File Manager
### Printer Status & Display
- **A1/A1 Mini Status Display** - Fixed incorrect "Printing" status when idle (Issue #168)
- **Chamber temp on A1/P1S** - Fixed regression where chamber temperature appeared on printers without sensors
- **Active AMS slot display** - Fixed for H2D printers with multiple AMS units
- **Printer hour counter** - Fixed not incrementing during prints and inconsistency between views
### AMS & Filament
- **Empty AMS Slot Recognition** - Fixed removed spools still appearing in Bambuddy (Issue #147)
- **Spoolman Sync for Transparent Spools** - Fixed sync failures for natural/transparent filaments (Issue #190)
- **Spoolman tag field** - Now auto-created on first connect, fixing fresh installs (Issue #123)
- **Spoolman 400 Bad Request** - Fixed when creating spools
- **AMS filament matching** - Fixed in reprint modal
- **User preset AMS configuration** - Fixed user presets showing empty fields in Bambu Studio
### Notifications & Webhooks
- **Progress Milestone Notifications** - Fixed showing wrong time (e.g., "17m" instead of "17h 47m") (Issue #157)
- **Mattermost/Slack Webhooks** - Added proper payload format support (Issue #133)
- **Telegram Notification Parsing** - Fixed markdown errors with underscores in error codes
- **HMS Error Notifications** - 853 error codes now translated to human-readable messages
- **Notifications sent when printer offline** - Fixed
### Camera & Streaming
- **Camera stream reconnection** - Automatic recovery from stalled streams
- **Camera zoom & pan** - Fixed pan range and added pinch-to-zoom for mobile (Issue #132)
- **P2S/X1E/H2 completion photo** - Fixed internal model codes not recognized (Issue #127)
- **Browser freeze** - Fixed on print completion when camera stream was open
- **ffmpeg processes** - Fixed not being killed when closing webcam window
### File Manager & Archives
- **P2S Empty Archive Tiles** - Fixed FTP search for printers without SD card (Issue #146)
- **File Manager folder navigation** - Fixed folder opening then jumping back to root (Issue #160)
- **File Manager upload** - Now accepts all file types, not just ZIP
- **Multi-plate 3MF metadata** - Single-plate exports now show correct thumbnail
- **Archive card cache** - Fixed wrong cover image bug
- **Archive delete safety** - Added checks to prevent deleting parent directories
### Statistics & Tracking
- **Print time stats** - Now uses actual elapsed time instead of slicer estimates (Issue #137)
- **Filament cost** - Now uses "Default filament cost" setting instead of hardcoded €25 (Issue #120)
- **Reprint cost tracking** - Now adds cost to existing total instead of replacing
- **K-Profiles backup status** - Fixed showing incorrect printer connection count
### Smart Plugs
- **HA Energy Sensors** - Fixed sensors with lowercase units (w, kwh) not detected (Issue #119)
### UI & UX
- **Skip objects modal overflow** - Fixed modal going above browser window (Issue #134)
- **Project card filament badges** - Fixed showing duplicates and raw color codes
- **Subnet scan serial number** - Fixed A1 Mini showing "unknown-*" placeholder (Issue #140)
- **Slicer protocol** - Fixed OS detection (Windows vs macOS/Linux)
### API & Backend
- **Settings API PATCH Method** - Added for Home Assistant rest_command compatibility (Issue #152)
- **GitHub Backup Timestamps** - Removed volatile timestamps for cleaner git diffs
- **Plate Calibration Persistence** - Fixed reference images not persisting in Docker
- **Update module** - Fixed for Docker-based installations
---
## Maintenance
- Upgraded vitest from 2.x to 3.x for security improvements
- Added security scanning (pip-audit, npm audit) to CI pipeline
- Replaced python-jose with PyJWT to eliminate ecdsa vulnerability
- Improved test coverage (796 backend tests, 518 frontend tests)
---
## Thank You!
This release wouldn't be possible without our amazing community. A huge thank you to everyone who contributed code, reported bugs, tested beta releases, and provided feedback!
### Code Contributors
| Contributor | Contribution |
|-------------|--------------|
| **[@maziggy](https://github.com/maziggy)** (MartinNYHC) | Lead developer, core features |
| **[@MisterBeardy](https://github.com/MisterBeardy)** (Wesley Reaves) | STL thumbnail generation |
| **[@JesseFPV](https://github.com/JesseFPV)** (Jesse Hulswit) | Optional authentication system |
### Issue Reporters & Testers
Special thanks to everyone who reported issues, tested beta releases, and provided valuable feedback:
- **[@Locxion](https://github.com/Locxion)** (Markus Bender) - A1 Mini status bug, log viewer feature
- **[@cadtoolbox](https://github.com/cadtoolbox)** (Thomas Rambach) - H2D Pro support, model-based queue
- **[@Twilek-de](https://github.com/Twilek-de)** - Empty AMS slots, Mattermost webhooks, progress milestones
- **[@elit3ge](https://github.com/elit3ge)** - Archive tiles, completion photos, upload improvements
- **[@opensourcefan](https://github.com/opensourcefan)** - Subnet scan serial, status colors
- **[@1nv4lidus3r](https://github.com/1nv4lidus3r)** - Print time stats, skip objects modal
- **[@joaorgoncalves](https://github.com/joaorgoncalves)** (João Gonçalves) - Filament cost settings, HA energy sync
- **[@beardofbeespool](https://github.com/beardofbeespool)** (Morton Likely) - STL thumbnail feature request
- **[@PeterXQChen](https://github.com/PeterXQChen)** (Peter Chen) - File manager folder navigation
- **[@Robnex](https://github.com/Robnex)** - External links, external spool sync
- **[@caco3](https://github.com/caco3)** (CaCO3) - Disable firmware checks
- **[@sbcrumb](https://github.com/sbcrumb)** - Camera zoom feature
- **[@fcps3](https://github.com/fcps3)** - Spoolman transparent spool sync
- **[@LucHeart](https://github.com/LucHeart)** - MQTT connection issues
- **[@ouihq](https://github.com/ouihq)** (Jonas) - File manager queue bug
- **[@Schuermi7](https://github.com/Schuermi7)** - AMS mapping, cloud 2FA
- **[@stubbers](https://github.com/stubbers)** (Joseph Stubberfield) - X1C sync issues
- **[@nvdmedianl](https://github.com/nvdmedianl)** (Nathan) - Spoolman Bambu spool errors
- **[@lbeumer-bit](https://github.com/lbeumer-bit)** - Notification photos
- **[@IROKILLER](https://github.com/IROKILLER)** - Home Assistant automations
- **[@fgrfn](https://github.com/fgrfn)** (Florian) - Dynamic electricity cost
- **[@JasonSwindle](https://github.com/JasonSwindle)** (Jason Swindle) - Smart plug text overflow
- **[@Cassiopeia1980](https://github.com/Cassiopeia1980)** - Connection issues
And many more community members who tested, provided feedback, and helped make Bambuddy better!
---
## Upgrade Notes
### From 0.1.5.x or earlier
- Database migrations run automatically on startup
- User authentication is optional and disabled by default
- Existing installations will continue to work without changes
### From 0.1.6 beta
- All beta migrations are included in the final release
- No action required - just update and restart
---
## What's Next?
We're already planning 0.1.7 with more exciting features. Stay tuned and keep the feedback coming!
- [GitHub Issues](https://github.com/MisterBeardy/bambuddy/issues) - Report bugs and request features
- [GitHub Discussions](https://github.com/MisterBeardy/bambuddy/discussions) - Join the conversation
---
**Happy Printing!** 🎉
*— The Bambuddy Team*
+57 -5
View File
@@ -1,6 +1,10 @@
"""External camera service.
Supports MJPEG streams, RTSP streams (via ffmpeg), HTTP snapshot URLs, and USB cameras.
Security Note: This service intentionally makes requests to user-configured camera URLs.
This is necessary functionality for external camera integration. URLs are validated
to ensure they are well-formed before use.
"""
import asyncio
@@ -9,12 +13,36 @@ import re
import shutil
from collections.abc import AsyncGenerator
from pathlib import Path
from urllib.parse import urlparse
import aiohttp
logger = logging.getLogger(__name__)
def _validate_camera_url(url: str, allowed_schemes: tuple[str, ...] = ("http", "https", "rtsp")) -> bool:
"""Validate camera URL format.
This validates that the URL is well-formed and uses an allowed scheme.
Note: This intentionally allows user-provided URLs as that is the
purpose of external camera configuration.
Args:
url: URL to validate
allowed_schemes: Tuple of allowed URL schemes
Returns:
True if URL is valid, False otherwise
"""
try:
parsed = urlparse(url)
if not parsed.scheme or not parsed.netloc:
return False
return parsed.scheme.lower() in allowed_schemes
except Exception:
return False
def list_usb_cameras() -> list[dict]:
"""List available USB cameras (V4L2 devices on Linux).
@@ -123,12 +151,23 @@ async def _capture_usb_frame(device: str, timeout: int) -> bytes | None:
logger.error("ffmpeg not found - required for USB camera capture")
return None
# Validate device path
# Validate device path - must be /dev/videoN format
if not device.startswith("/dev/video"):
logger.error(f"Invalid USB device path: {device}")
return None
if not Path(device).exists():
# Additional path validation to prevent path traversal
# Resolve to absolute path and verify it's still under /dev/
try:
resolved_path = Path(device).resolve()
if not str(resolved_path).startswith("/dev/video"):
logger.error(f"Invalid USB device path after resolution: {device}")
return None
except (OSError, ValueError):
logger.error(f"Failed to resolve USB device path: {device}")
return None
if not resolved_path.exists(): # nosec B108 - path validated above
logger.error(f"USB device does not exist: {device}")
return None
@@ -182,10 +221,15 @@ async def _capture_usb_frame(device: str, timeout: int) -> bytes | None:
async def _capture_mjpeg_frame(url: str, timeout: int) -> bytes | None:
"""Extract single frame from MJPEG stream."""
# Validate URL format (user-configured camera URL - intentional external request)
if not _validate_camera_url(url, ("http", "https")):
logger.error(f"Invalid MJPEG URL format: {url[:50]}...")
return None
try:
async with (
aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout)) as session,
session.get(url) as response,
session.get(url) as response, # nosec B113 - URL validated above, user-configured camera
):
if response.status != 200:
logger.error(f"MJPEG stream returned status {response.status}")
@@ -287,10 +331,15 @@ async def _capture_rtsp_frame(url: str, timeout: int) -> bytes | None:
async def _capture_snapshot(url: str, timeout: int) -> bytes | None:
"""Fetch snapshot from HTTP URL."""
# Validate URL format (user-configured camera URL - intentional external request)
if not _validate_camera_url(url, ("http", "https")):
logger.error(f"Invalid snapshot URL format: {url[:50]}...")
return None
try:
async with (
aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout)) as session,
session.get(url) as response,
session.get(url) as response, # nosec B113 - URL validated above, user-configured camera
):
if response.status != 200:
logger.error(f"Snapshot URL returned status {response.status}")
@@ -348,7 +397,10 @@ async def test_connection(url: str, camera_type: str) -> dict:
return {"success": False, "error": "Failed to capture frame from camera"}
except Exception as e:
return {"success": False, "error": str(e)}
# Sanitize error message - don't expose internal details
error_type = type(e).__name__
logger.error(f"Camera connection test failed: {e}")
return {"success": False, "error": f"Connection failed: {error_type}"}
async def generate_mjpeg_stream(url: str, camera_type: str, fps: int = 10) -> AsyncGenerator[bytes, None]:
+17 -4
View File
@@ -165,17 +165,30 @@ class GitHubBackupService:
except Exception as e:
logger.error(f"GitHub connection test failed: {e}")
return {"success": False, "message": str(e), "repo_name": None, "permissions": None}
# Sanitize error - don't expose internal details
error_type = type(e).__name__
return {
"success": False,
"message": f"Connection failed: {error_type}",
"repo_name": None,
"permissions": None,
}
def _parse_repo_url(self, url: str) -> tuple[str, str]:
"""Parse owner and repo from GitHub URL."""
# Handle HTTPS URLs
match = re.match(r"https://github\.com/([^/]+)/([^/]+?)(?:\.git)?/?$", url)
# Limit URL length to prevent ReDoS attacks
if not url or len(url) > 500:
raise ValueError("Invalid GitHub URL: URL too long or empty")
# Handle HTTPS URLs - use atomic groups via limited character classes
# GitHub usernames: 1-39 chars, alphanumeric and hyphens
# Repo names: 1-100 chars, alphanumeric, hyphens, underscores, dots
match = re.match(r"https://github\.com/([\w-]{1,39})/([\w.\-]{1,100})(?:\.git)?/?$", url)
if match:
return match.group(1), match.group(2)
# Handle SSH URLs
match = re.match(r"git@github\.com:([^/]+)/([^/]+?)(?:\.git)?$", url)
match = re.match(r"git@github\.com:([\w-]{1,39})/([\w.\-]{1,100})(?:\.git)?$", url)
if match:
return match.group(1), match.group(2)