mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
The bug report endpoints (start-logging, stop-logging, submit) had no authentication, allowing anyone on the network to enable debug logging, retrieve sanitized system logs, and trigger bug report submissions when auth was enabled. All three now require permission when auth is enabled: start-logging requires settings:update, stop-logging and submit require settings:read. Endpoints remain open when auth is disabled (default).
112 lines
3.4 KiB
Python
112 lines
3.4 KiB
Python
"""Bug report endpoint for submitting user bug reports to GitHub."""
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Query
|
|
from pydantic import BaseModel
|
|
|
|
from backend.app.api.routes.support import (
|
|
_apply_log_level,
|
|
_collect_support_info,
|
|
_get_debug_setting,
|
|
_get_recent_sanitized_logs,
|
|
_set_debug_setting,
|
|
)
|
|
from backend.app.core.auth import RequirePermissionIfAuthEnabled
|
|
from backend.app.core.database import async_session
|
|
from backend.app.core.permissions import Permission
|
|
from backend.app.models.user import User
|
|
from backend.app.services.bug_report import submit_report
|
|
from backend.app.services.printer_manager import printer_manager
|
|
|
|
router = APIRouter(prefix="/bug-report", tags=["bug-report"])
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class BugReportRequest(BaseModel):
|
|
description: str
|
|
email: str | None = None
|
|
screenshot_base64: str | None = None
|
|
include_support_info: bool = True
|
|
debug_logs: str | None = None
|
|
|
|
|
|
class BugReportResponse(BaseModel):
|
|
success: bool
|
|
message: str
|
|
issue_url: str | None = None
|
|
issue_number: int | None = None
|
|
|
|
|
|
class StartLoggingResponse(BaseModel):
|
|
started: bool
|
|
was_debug: bool
|
|
|
|
|
|
class StopLoggingResponse(BaseModel):
|
|
logs: str
|
|
|
|
|
|
@router.post("/start-logging", response_model=StartLoggingResponse)
|
|
async def start_logging(
|
|
_: User | None = RequirePermissionIfAuthEnabled(Permission.SETTINGS_UPDATE),
|
|
):
|
|
"""Enable debug logging and push all printers for fresh data."""
|
|
async with async_session() as db:
|
|
was_debug, _ = await _get_debug_setting(db)
|
|
|
|
if not was_debug:
|
|
async with async_session() as db:
|
|
await _set_debug_setting(db, True)
|
|
_apply_log_level(True)
|
|
logger.info("Bug report: enabled debug logging")
|
|
|
|
for printer_id in list(printer_manager._clients.keys()):
|
|
try:
|
|
printer_manager.request_status_update(printer_id)
|
|
except Exception:
|
|
logger.debug("Failed to push_all for printer %s", printer_id)
|
|
|
|
return StartLoggingResponse(started=True, was_debug=was_debug)
|
|
|
|
|
|
@router.post("/stop-logging", response_model=StopLoggingResponse)
|
|
async def stop_logging(
|
|
was_debug: bool = Query(default=False),
|
|
_: User | None = RequirePermissionIfAuthEnabled(Permission.SETTINGS_READ),
|
|
):
|
|
"""Collect logs and restore previous log level."""
|
|
logs = await _get_recent_sanitized_logs()
|
|
|
|
if not was_debug:
|
|
async with async_session() as db:
|
|
await _set_debug_setting(db, False)
|
|
_apply_log_level(False)
|
|
logger.info("Bug report: restored normal logging")
|
|
|
|
return StopLoggingResponse(logs=logs)
|
|
|
|
|
|
@router.post("/submit", response_model=BugReportResponse)
|
|
async def submit_bug_report(
|
|
report: BugReportRequest,
|
|
_: User | None = RequirePermissionIfAuthEnabled(Permission.SETTINGS_READ),
|
|
):
|
|
"""Submit a bug report. Requires auth when authentication is enabled."""
|
|
support_info = None
|
|
if report.include_support_info:
|
|
try:
|
|
support_info = await _collect_support_info()
|
|
if report.debug_logs:
|
|
support_info["recent_logs"] = report.debug_logs
|
|
except Exception:
|
|
logger.exception("Failed to collect support info for bug report")
|
|
|
|
result = await submit_report(
|
|
description=report.description,
|
|
reporter_email=report.email,
|
|
screenshot_base64=report.screenshot_base64,
|
|
support_info=support_info,
|
|
)
|
|
return BugReportResponse(**result)
|