Files
maziggy 610431d6b7 Add optional PostgreSQL database support
Bambuddy can now use an external PostgreSQL database via the
  DATABASE_URL environment variable. SQLite remains the default.
  Dialect-aware helpers handle upserts, PRAGMAs, FTS (FTS5 vs
  tsvector+GIN), backup/restore, and health checks. All migration
  blocks use savepoints to prevent Postgres transaction poisoning.
  Backups are always portable SQLite format regardless of backend.
  Cross-database restore imports SQLite backups into PostgreSQL
  with automatic boolean/datetime conversion, NOT NULL default
  filling, and FK constraint handling.
2026-04-03 11:33:29 +02:00

31 lines
1.3 KiB
Python

from datetime import datetime
from sqlalchemy import JSON, Boolean, DateTime, String, func
from sqlalchemy.orm import Mapped, mapped_column
from backend.app.core.database import Base
class APIKey(Base):
"""API key for external webhook access."""
__tablename__ = "api_keys"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100)) # User-friendly name
key_hash: Mapped[str] = mapped_column(String(255)) # bcrypt hash of the key
key_prefix: Mapped[str] = mapped_column(String(20)) # First 8 chars + "..." for display
# Permissions
can_queue: Mapped[bool] = mapped_column(Boolean, default=True) # Add to queue
can_control_printer: Mapped[bool] = mapped_column(Boolean, default=False) # Start/stop/cancel
can_read_status: Mapped[bool] = mapped_column(Boolean, default=True) # Query status
# Optional scope limits
printer_ids: Mapped[list | None] = mapped_column(JSON, nullable=True) # null = all printers
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
last_used: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
expires_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) # Optional expiry