mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
PROJECTS_CREATE/UPDATE/DELETE were in _APIKEY_DENIED_PERMISSIONS with no entry in _APIKEY_SCOPE_BY_PERMISSION, so every project mutation returned a generic 403 for any API key regardless of granted permissions -- the same regression class as archives (#1888) and library (#1832). Add a per-key can_manage_projects scope. Project routes gate on plain PROJECTS_* (no OWN/ALL split), so all three CRUD permissions map to the one scope; membership edits (add-archives) gate on PROJECTS_UPDATE and are covered. PROJECTS_READ is unchanged (already under can_read_status). Column defaults TRUE for new keys; existing rows backfill to FALSE so the upgrade never silently widens scope. Migration is BOOLEAN (SQLite + Postgres safe), verified on fresh SQLite and Postgres 17. Bundled SpoolBuddy kiosk key set to False. Settings API-key UI gets a Manage Projects toggle + Projects badge; 11-locale i18n. RBAC scope matrix + drift guards extended.
76 lines
2.6 KiB
Python
76 lines
2.6 KiB
Python
from datetime import datetime
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class APIKeyCreate(BaseModel):
|
|
"""Schema for creating a new API key."""
|
|
|
|
name: str
|
|
can_queue: bool = True
|
|
can_control_printer: bool = False
|
|
can_read_status: bool = True
|
|
can_manage_library: bool = True # Upload / rename / delete own library files + MakerWorld import
|
|
can_manage_inventory: bool = True # Inventory writes — SpoolBuddy NFC/scale/system, manual stock edits via API
|
|
can_manage_maintenance: bool = (
|
|
True # Log/reset maintenance items, edit intervals, manage type catalog (#1832 follow-up)
|
|
)
|
|
can_manage_archives: bool = True # Create/update/delete print archives — not purge (#1888)
|
|
can_manage_projects: bool = True # Create/update/delete projects + membership (add archives) (#1893)
|
|
can_access_cloud: bool = False # Read /cloud/* on the creator's behalf — default off (#1182)
|
|
can_update_energy_cost: bool = False # POST /settings/electricity-price only (#1356)
|
|
printer_ids: list[int] | None = None # null = all printers
|
|
expires_at: datetime | None = None
|
|
|
|
|
|
class APIKeyUpdate(BaseModel):
|
|
"""Schema for updating an API key."""
|
|
|
|
name: str | None = None
|
|
can_queue: bool | None = None
|
|
can_control_printer: bool | None = None
|
|
can_read_status: bool | None = None
|
|
can_manage_library: bool | None = None
|
|
can_manage_inventory: bool | None = None
|
|
can_manage_maintenance: bool | None = None
|
|
can_manage_archives: bool | None = None
|
|
can_manage_projects: bool | None = None
|
|
can_access_cloud: bool | None = None
|
|
can_update_energy_cost: bool | None = None
|
|
printer_ids: list[int] | None = None
|
|
enabled: bool | None = None
|
|
expires_at: datetime | None = None
|
|
|
|
|
|
class APIKeyResponse(BaseModel):
|
|
"""Schema for API key response (without full key)."""
|
|
|
|
id: int
|
|
name: str
|
|
key_prefix: str # First 8 chars for identification
|
|
user_id: int | None # Owner — NULL on legacy keys created before per-user ownership (#1182)
|
|
can_queue: bool
|
|
can_control_printer: bool
|
|
can_read_status: bool
|
|
can_manage_library: bool
|
|
can_manage_inventory: bool
|
|
can_manage_maintenance: bool
|
|
can_manage_archives: bool
|
|
can_manage_projects: bool
|
|
can_access_cloud: bool
|
|
can_update_energy_cost: bool
|
|
printer_ids: list[int] | None
|
|
enabled: bool
|
|
last_used: datetime | None
|
|
created_at: datetime
|
|
expires_at: datetime | None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class APIKeyCreateResponse(APIKeyResponse):
|
|
"""Response when creating a key - includes full key (shown only once)."""
|
|
|
|
key: str # Full API key, only shown on creation
|