Files
bambuddy/backend/app/core/permissions.py
T
maziggy 3480d39434 Browse a Manyfold library and import its files (issue #1471)
The MakerWorld page becomes Model Sources, with a MakerWorld tab and a
Manyfold tab. Bambuddy signs in to a self-hosted Manyfold with an OAuth
application (public read scopes), lists and searches its models with their
previews, and imports 3MF, STL and STEP files into the library, from where
they are sliced and printed like any other file.

New permissions manyfold:view and manyfold:import are granted once to the
groups that hold the matching MakerWorld permissions. The client secret is
never returned and is left out of GitHub backups. The Manyfold URL and every
redirect pass the LAN-service URL check. Old /makerworld links open the
MakerWorld tab.

Several files import at once: tick files in a model, or Select all, then
Import selected or Import all; or tick models in the grid and import all
their printable files. Files import one after another, failures don't stop
the rest, and a summary reports the outcome.
2026-10-04 13:09:25 +02:00

542 lines
20 KiB
Python

"""Permission definitions for the group-based access control system.
This module defines all permissions using a string enum with `resource:action` naming.
Permissions are additive across groups - a user has all permissions from all their groups.
"""
from backend.app.core.compat import StrEnum
class Permission(StrEnum):
"""All available permissions in the system.
Permissions follow the pattern: resource:action
Actions typically include: read, create, update, delete, plus resource-specific actions.
"""
# Printers
PRINTERS_READ = "printers:read"
PRINTERS_CREATE = "printers:create"
PRINTERS_UPDATE = "printers:update"
PRINTERS_DELETE = "printers:delete"
PRINTERS_CONTROL = "printers:control" # Printer controls: stop/pause/resume, lights, motors, drying, etc.
PRINTERS_FILES = "printers:files" # Send files to printer
PRINTERS_AMS_RFID = "printers:ams_rfid" # Re-read AMS RFID tags
PRINTERS_CLEAR_PLATE = "printers:clear_plate" # Confirm plate cleared for next print
# Archives
# ARCHIVES_READ kept for backward-compat with legacy custom roles, but new
# role bootstraps use the ownership-split variants below. seed_default_groups
# migrates pre-existing role rows: Administrators → ALL, everyone else → OWN.
ARCHIVES_READ = "archives:read"
ARCHIVES_READ_OWN = "archives:read_own"
ARCHIVES_READ_ALL = "archives:read_all"
ARCHIVES_CREATE = "archives:create"
ARCHIVES_UPDATE_OWN = "archives:update_own"
ARCHIVES_UPDATE_ALL = "archives:update_all"
ARCHIVES_DELETE_OWN = "archives:delete_own"
ARCHIVES_DELETE_ALL = "archives:delete_all"
ARCHIVES_REPRINT_OWN = "archives:reprint_own" # Reprint own archives; queue:create is also required to enqueue
ARCHIVES_REPRINT_ALL = "archives:reprint_all" # Reprint any archive; queue:create is also required to enqueue
ARCHIVES_PURGE = "archives:purge"
# Queue
QUEUE_READ = "queue:read"
QUEUE_READ_OWN = "queue:read_own"
QUEUE_READ_ALL = "queue:read_all"
QUEUE_CREATE = "queue:create" # Create queue items, including ASAP items eligible for immediate dispatch
QUEUE_UPDATE_OWN = "queue:update_own"
QUEUE_UPDATE_ALL = "queue:update_all"
QUEUE_DELETE_OWN = "queue:delete_own"
QUEUE_DELETE_ALL = "queue:delete_all"
QUEUE_REORDER = "queue:reorder"
# Library
LIBRARY_READ = "library:read"
LIBRARY_READ_OWN = "library:read_own"
LIBRARY_READ_ALL = "library:read_all"
LIBRARY_UPLOAD = "library:upload" # Upload/import/slice library files; queue:create is also required to print
LIBRARY_UPDATE_OWN = "library:update_own"
LIBRARY_UPDATE_ALL = "library:update_all"
LIBRARY_DELETE_OWN = "library:delete_own"
LIBRARY_DELETE_ALL = "library:delete_all"
# Admin-only: bulk purge of old files + trash retention settings (#1008).
# Routine per-user trash management (restore-own, hard-delete-own) is
# gated by the existing LIBRARY_DELETE_* permissions instead.
LIBRARY_PURGE = "library:purge"
# Projects
PROJECTS_READ = "projects:read"
PROJECTS_CREATE = "projects:create"
PROJECTS_UPDATE = "projects:update"
PROJECTS_DELETE = "projects:delete"
# Filaments
FILAMENTS_READ = "filaments:read"
FILAMENTS_CREATE = "filaments:create"
FILAMENTS_UPDATE = "filaments:update"
FILAMENTS_DELETE = "filaments:delete"
# Inventory (Spool Inventory, Spool Catalog, Color Catalog)
INVENTORY_READ = "inventory:read"
INVENTORY_CREATE = "inventory:create"
INVENTORY_UPDATE = "inventory:update"
INVENTORY_DELETE = "inventory:delete"
INVENTORY_VIEW_ASSIGNMENTS = "inventory:view_assignments" # View spool-to-AMS assignments on printer cards
INVENTORY_FORECAST_READ = "inventory:forecast_read" # View forecast/reorder intelligence panel
INVENTORY_FORECAST_WRITE = "inventory:forecast_write" # Modify SKU settings, lead times, shopping list
# Smart Plugs
SMART_PLUGS_READ = "smart_plugs:read"
SMART_PLUGS_CREATE = "smart_plugs:create"
SMART_PLUGS_UPDATE = "smart_plugs:update"
SMART_PLUGS_DELETE = "smart_plugs:delete"
SMART_PLUGS_CONTROL = "smart_plugs:control" # Turn on/off
# Camera
CAMERA_VIEW = "camera:view"
# Maintenance
MAINTENANCE_READ = "maintenance:read"
MAINTENANCE_CREATE = "maintenance:create"
MAINTENANCE_UPDATE = "maintenance:update"
MAINTENANCE_DELETE = "maintenance:delete"
# K-Profiles
KPROFILES_READ = "kprofiles:read"
KPROFILES_CREATE = "kprofiles:create"
KPROFILES_UPDATE = "kprofiles:update"
KPROFILES_DELETE = "kprofiles:delete"
# Notifications
NOTIFICATIONS_READ = "notifications:read"
NOTIFICATIONS_CREATE = "notifications:create"
NOTIFICATIONS_UPDATE = "notifications:update"
NOTIFICATIONS_DELETE = "notifications:delete"
NOTIFICATIONS_USER_EMAIL = "notifications:user_email" # Receive per-user print email notifications
# Notification Templates
NOTIFICATION_TEMPLATES_READ = "notification_templates:read"
NOTIFICATION_TEMPLATES_UPDATE = "notification_templates:update"
# External Links
EXTERNAL_LINKS_READ = "external_links:read"
EXTERNAL_LINKS_CREATE = "external_links:create"
EXTERNAL_LINKS_UPDATE = "external_links:update"
EXTERNAL_LINKS_DELETE = "external_links:delete"
# Discovery (network scanning)
DISCOVERY_SCAN = "discovery:scan"
# Firmware
FIRMWARE_READ = "firmware:read"
FIRMWARE_UPDATE = "firmware:update"
# AMS History
AMS_HISTORY_READ = "ams_history:read"
PRINTER_SENSOR_HISTORY_READ = "printer_sensor_history:read"
# Stats/Metrics
STATS_READ = "stats:read"
STATS_FILTER_BY_USER = "stats:filter_by_user"
# Cost Centers
COST_CENTERS_READ_OWN = "cost_centers:read_own"
COST_CENTERS_READ_ALL = "cost_centers:read_all"
COST_CENTERS_MODIFY = "cost_centers:modify"
COST_CENTERS_CREATE = "cost_centers:create"
# System Info
SYSTEM_READ = "system:read"
# Settings (admin-level)
SETTINGS_READ = "settings:read"
SETTINGS_UPDATE = "settings:update"
SETTINGS_BACKUP = "settings:backup"
SETTINGS_RESTORE = "settings:restore"
# GitHub Backup (admin-level)
GITHUB_BACKUP = "github:backup"
GITHUB_RESTORE = "github:restore"
# Cloud Auth (admin-level)
CLOUD_AUTH = "cloud:auth"
ORCA_CLOUD_AUTH = "orca_cloud:auth"
# MakerWorld Integration
MAKERWORLD_VIEW = "makerworld:view" # Resolve MakerWorld URLs and view model metadata
MAKERWORLD_IMPORT = "makerworld:import" # Download 3MFs from MakerWorld into the library
# Manyfold Integration (#1471)
MANYFOLD_VIEW = "manyfold:view" # Browse and search the connected Manyfold library
MANYFOLD_IMPORT = "manyfold:import" # Download Manyfold files into the library
# API Keys (admin-level)
API_KEYS_READ = "api_keys:read"
API_KEYS_CREATE = "api_keys:create"
API_KEYS_UPDATE = "api_keys:update"
API_KEYS_DELETE = "api_keys:delete"
# Users (admin-level)
USERS_READ = "users:read"
# Narrow read: id + username only, no emails/roles/groups/permissions (#1894).
# Exists so an id -> name mapping can be resolved without handing out the
# full user objects. Pairs with STATS_FILTER_BY_USER, which is useless
# without a way to discover the ids it filters on.
USERS_READ_SLIM = "users:read_slim"
USERS_CREATE = "users:create"
USERS_UPDATE = "users:update"
USERS_DELETE = "users:delete"
# Groups (admin-level)
GROUPS_READ = "groups:read"
GROUPS_CREATE = "groups:create"
GROUPS_UPDATE = "groups:update"
GROUPS_DELETE = "groups:delete"
# Slicer Pipelines (#1425)
PIPELINES_READ = "pipelines:read" # View pipeline definitions and run history
PIPELINES_WRITE = "pipelines:write" # Create / edit / delete pipeline definitions
PIPELINES_RUN = "pipelines:run" # Kick off a pipeline run (PR C); separate because spending filament is a different trust dimension than authoring the recipe
# WebSocket connection
WEBSOCKET_CONNECT = "websocket:connect"
# Permission categories for UI organization
PERMISSION_CATEGORIES = {
"Printers": [
Permission.PRINTERS_READ,
Permission.PRINTERS_CREATE,
Permission.PRINTERS_UPDATE,
Permission.PRINTERS_DELETE,
Permission.PRINTERS_CONTROL,
Permission.PRINTERS_FILES,
Permission.PRINTERS_AMS_RFID,
Permission.PRINTERS_CLEAR_PLATE,
],
"Archives": [
Permission.ARCHIVES_READ, # legacy — kept for back-compat with custom roles
Permission.ARCHIVES_READ_OWN,
Permission.ARCHIVES_READ_ALL,
Permission.ARCHIVES_CREATE,
Permission.ARCHIVES_UPDATE_OWN,
Permission.ARCHIVES_UPDATE_ALL,
Permission.ARCHIVES_DELETE_OWN,
Permission.ARCHIVES_DELETE_ALL,
Permission.ARCHIVES_REPRINT_OWN,
Permission.ARCHIVES_REPRINT_ALL,
Permission.ARCHIVES_PURGE,
],
"Queue": [
Permission.QUEUE_READ, # legacy — kept for back-compat with custom roles
Permission.QUEUE_READ_OWN,
Permission.QUEUE_READ_ALL,
Permission.QUEUE_CREATE,
Permission.QUEUE_UPDATE_OWN,
Permission.QUEUE_UPDATE_ALL,
Permission.QUEUE_DELETE_OWN,
Permission.QUEUE_DELETE_ALL,
Permission.QUEUE_REORDER,
],
"Library": [
Permission.LIBRARY_READ, # legacy — kept for back-compat with custom roles
Permission.LIBRARY_READ_OWN,
Permission.LIBRARY_READ_ALL,
Permission.LIBRARY_UPLOAD,
Permission.LIBRARY_UPDATE_OWN,
Permission.LIBRARY_UPDATE_ALL,
Permission.LIBRARY_DELETE_OWN,
Permission.LIBRARY_DELETE_ALL,
Permission.LIBRARY_PURGE,
],
"Projects": [
Permission.PROJECTS_READ,
Permission.PROJECTS_CREATE,
Permission.PROJECTS_UPDATE,
Permission.PROJECTS_DELETE,
],
"Filaments": [
Permission.FILAMENTS_READ,
Permission.FILAMENTS_CREATE,
Permission.FILAMENTS_UPDATE,
Permission.FILAMENTS_DELETE,
],
"Inventory": [
Permission.INVENTORY_READ,
Permission.INVENTORY_CREATE,
Permission.INVENTORY_UPDATE,
Permission.INVENTORY_DELETE,
Permission.INVENTORY_VIEW_ASSIGNMENTS,
Permission.INVENTORY_FORECAST_READ,
Permission.INVENTORY_FORECAST_WRITE,
],
"Smart Plugs": [
Permission.SMART_PLUGS_READ,
Permission.SMART_PLUGS_CREATE,
Permission.SMART_PLUGS_UPDATE,
Permission.SMART_PLUGS_DELETE,
Permission.SMART_PLUGS_CONTROL,
],
"Camera": [
Permission.CAMERA_VIEW,
],
"Maintenance": [
Permission.MAINTENANCE_READ,
Permission.MAINTENANCE_CREATE,
Permission.MAINTENANCE_UPDATE,
Permission.MAINTENANCE_DELETE,
],
"K-Profiles": [
Permission.KPROFILES_READ,
Permission.KPROFILES_CREATE,
Permission.KPROFILES_UPDATE,
Permission.KPROFILES_DELETE,
],
"Notifications": [
Permission.NOTIFICATIONS_READ,
Permission.NOTIFICATIONS_CREATE,
Permission.NOTIFICATIONS_UPDATE,
Permission.NOTIFICATIONS_DELETE,
Permission.NOTIFICATIONS_USER_EMAIL,
Permission.NOTIFICATION_TEMPLATES_READ,
Permission.NOTIFICATION_TEMPLATES_UPDATE,
],
"External Links": [
Permission.EXTERNAL_LINKS_READ,
Permission.EXTERNAL_LINKS_CREATE,
Permission.EXTERNAL_LINKS_UPDATE,
Permission.EXTERNAL_LINKS_DELETE,
],
"Discovery": [
Permission.DISCOVERY_SCAN,
],
"Firmware": [
Permission.FIRMWARE_READ,
Permission.FIRMWARE_UPDATE,
],
"Stats & History": [
Permission.AMS_HISTORY_READ,
Permission.PRINTER_SENSOR_HISTORY_READ,
Permission.STATS_READ,
Permission.STATS_FILTER_BY_USER,
],
"Finance": [
Permission.COST_CENTERS_READ_OWN,
Permission.COST_CENTERS_READ_ALL,
Permission.COST_CENTERS_MODIFY,
Permission.COST_CENTERS_CREATE,
],
"System": [
Permission.SYSTEM_READ,
],
"Settings": [
Permission.SETTINGS_READ,
Permission.SETTINGS_UPDATE,
Permission.SETTINGS_BACKUP,
Permission.SETTINGS_RESTORE,
],
"Backup": [
Permission.GITHUB_BACKUP,
Permission.GITHUB_RESTORE,
],
"Cloud": [
Permission.CLOUD_AUTH,
Permission.ORCA_CLOUD_AUTH,
],
"MakerWorld": [
Permission.MAKERWORLD_VIEW,
Permission.MAKERWORLD_IMPORT,
],
"Manyfold": [
Permission.MANYFOLD_VIEW,
Permission.MANYFOLD_IMPORT,
],
"API Keys": [
Permission.API_KEYS_READ,
Permission.API_KEYS_CREATE,
Permission.API_KEYS_UPDATE,
Permission.API_KEYS_DELETE,
],
"User Management": [
Permission.USERS_READ,
Permission.USERS_READ_SLIM,
Permission.USERS_CREATE,
Permission.USERS_UPDATE,
Permission.USERS_DELETE,
Permission.GROUPS_READ,
Permission.GROUPS_CREATE,
Permission.GROUPS_UPDATE,
Permission.GROUPS_DELETE,
],
"Slicer Pipelines": [
Permission.PIPELINES_READ,
Permission.PIPELINES_WRITE,
Permission.PIPELINES_RUN,
],
"WebSocket": [
Permission.WEBSOCKET_CONNECT,
],
}
# All permissions as a list
ALL_PERMISSIONS = [p.value for p in Permission]
# Default group definitions
DEFAULT_GROUPS = {
"Administrators": {
"description": "Full access to all features and settings",
"permissions": ALL_PERMISSIONS, # All permissions
"is_system": True,
},
"Operators": {
"description": "Can control printers, manage queue and archives, view settings",
"permissions": [
# Printers - full control
Permission.PRINTERS_READ.value,
Permission.PRINTERS_CREATE.value,
Permission.PRINTERS_UPDATE.value,
Permission.PRINTERS_DELETE.value,
Permission.PRINTERS_CONTROL.value,
Permission.PRINTERS_FILES.value,
Permission.PRINTERS_AMS_RFID.value,
Permission.PRINTERS_CLEAR_PLATE.value,
# Archives - own items only
Permission.ARCHIVES_READ_OWN.value,
Permission.ARCHIVES_CREATE.value,
Permission.ARCHIVES_UPDATE_OWN.value,
Permission.ARCHIVES_DELETE_OWN.value,
Permission.ARCHIVES_REPRINT_OWN.value,
# Queue - own items only
Permission.QUEUE_READ_OWN.value,
Permission.QUEUE_CREATE.value,
Permission.QUEUE_UPDATE_OWN.value,
Permission.QUEUE_DELETE_OWN.value,
Permission.QUEUE_REORDER.value,
# Library - own items only
Permission.LIBRARY_READ_OWN.value,
Permission.LIBRARY_UPLOAD.value,
Permission.LIBRARY_UPDATE_OWN.value,
Permission.LIBRARY_DELETE_OWN.value,
# MakerWorld integration
Permission.MAKERWORLD_VIEW.value,
Permission.MAKERWORLD_IMPORT.value,
# Manyfold integration
Permission.MANYFOLD_VIEW.value,
Permission.MANYFOLD_IMPORT.value,
# Orca Cloud — needed for the Slice modal's Orca Cloud preset
# picker to populate. Workshops that use Orca Cloud presets
# need every operator to be able to authenticate. Bambu Cloud
# (CLOUD_AUTH) stays admin-only — that one is a more sensitive
# account binding.
Permission.ORCA_CLOUD_AUTH.value,
# Projects - full access
Permission.PROJECTS_READ.value,
Permission.PROJECTS_CREATE.value,
Permission.PROJECTS_UPDATE.value,
Permission.PROJECTS_DELETE.value,
# Filaments - full access
Permission.FILAMENTS_READ.value,
Permission.FILAMENTS_CREATE.value,
Permission.FILAMENTS_UPDATE.value,
Permission.FILAMENTS_DELETE.value,
# Inventory - full access
Permission.INVENTORY_READ.value,
Permission.INVENTORY_CREATE.value,
Permission.INVENTORY_UPDATE.value,
Permission.INVENTORY_DELETE.value,
Permission.INVENTORY_VIEW_ASSIGNMENTS.value,
Permission.INVENTORY_FORECAST_READ.value,
Permission.INVENTORY_FORECAST_WRITE.value,
# Smart Plugs - full access
Permission.SMART_PLUGS_READ.value,
Permission.SMART_PLUGS_CREATE.value,
Permission.SMART_PLUGS_UPDATE.value,
Permission.SMART_PLUGS_DELETE.value,
Permission.SMART_PLUGS_CONTROL.value,
# Camera - view
Permission.CAMERA_VIEW.value,
# Maintenance - full access
Permission.MAINTENANCE_READ.value,
Permission.MAINTENANCE_CREATE.value,
Permission.MAINTENANCE_UPDATE.value,
Permission.MAINTENANCE_DELETE.value,
# K-Profiles - full access
Permission.KPROFILES_READ.value,
Permission.KPROFILES_CREATE.value,
Permission.KPROFILES_UPDATE.value,
Permission.KPROFILES_DELETE.value,
# Notifications - full access
Permission.NOTIFICATIONS_READ.value,
Permission.NOTIFICATIONS_CREATE.value,
Permission.NOTIFICATIONS_UPDATE.value,
Permission.NOTIFICATIONS_DELETE.value,
Permission.NOTIFICATIONS_USER_EMAIL.value,
Permission.NOTIFICATION_TEMPLATES_READ.value,
Permission.NOTIFICATION_TEMPLATES_UPDATE.value,
# External Links - full access
Permission.EXTERNAL_LINKS_READ.value,
Permission.EXTERNAL_LINKS_CREATE.value,
Permission.EXTERNAL_LINKS_UPDATE.value,
Permission.EXTERNAL_LINKS_DELETE.value,
# Discovery
Permission.DISCOVERY_SCAN.value,
# Firmware - read only
Permission.FIRMWARE_READ.value,
# Stats & History
Permission.AMS_HISTORY_READ.value,
Permission.PRINTER_SENSOR_HISTORY_READ.value,
Permission.STATS_READ.value,
Permission.SYSTEM_READ.value,
# Finance - own visibility
Permission.COST_CENTERS_READ_OWN.value,
# Settings - read only
Permission.SETTINGS_READ.value,
# Slicer Pipelines - full access
Permission.PIPELINES_READ.value,
Permission.PIPELINES_WRITE.value,
Permission.PIPELINES_RUN.value,
# WebSocket
Permission.WEBSOCKET_CONNECT.value,
],
"is_system": True,
},
"Viewers": {
"description": "Read-only access to printers, archives, and queue",
"permissions": [
# Read-only access
Permission.PRINTERS_READ.value,
Permission.ARCHIVES_READ_OWN.value,
Permission.QUEUE_READ_OWN.value,
Permission.LIBRARY_READ_OWN.value,
Permission.PROJECTS_READ.value,
Permission.FILAMENTS_READ.value,
Permission.INVENTORY_READ.value,
Permission.INVENTORY_VIEW_ASSIGNMENTS.value,
Permission.INVENTORY_FORECAST_READ.value,
Permission.SMART_PLUGS_READ.value,
Permission.CAMERA_VIEW.value,
Permission.MAINTENANCE_READ.value,
Permission.KPROFILES_READ.value,
Permission.NOTIFICATIONS_READ.value,
Permission.NOTIFICATION_TEMPLATES_READ.value,
Permission.EXTERNAL_LINKS_READ.value,
Permission.FIRMWARE_READ.value,
Permission.AMS_HISTORY_READ.value,
Permission.PRINTER_SENSOR_HISTORY_READ.value,
Permission.STATS_READ.value,
Permission.SYSTEM_READ.value,
Permission.SETTINGS_READ.value,
# Slicer Pipelines - read only
Permission.PIPELINES_READ.value,
Permission.WEBSOCKET_CONNECT.value,
# MakerWorld browsing only (no import — that writes to library)
Permission.MAKERWORLD_VIEW.value,
# Manyfold browsing only, for the same reason
Permission.MANYFOLD_VIEW.value,
],
"is_system": True,
},
}