3 Commits
Author SHA1 Message Date
maziggy fe07fbd07b Give groups whole locations and a printer access page (issue #1727)
A group can now be given locations as well as single printers: it then
reaches every printer in them, including printers added there later.
Printer access moves out of the group editor to Settings ->
Authentication -> Printer access, built for large fleets: groups and
printers searchable and filtered by location, model and access, edited
by group or by printer, saved together. "Who has access" in the printer
card menu opens it on that printer.

- group_locations table; the scope is picked printers plus printers
  whose location matches.
- Moving a printer into or out of a location a limited group has is
  admin-only, and open connections are rescoped. The edit dialog names
  the groups a move affects. Locations are trimmed on save.
- Clearing a printer's location in the edit dialog now clears it.
2026-10-02 07:30:04 +02:00
maziggy 45921b7a56 Limit groups to selected printers (issue #1727)
A group can now be limited to a set of printers. Its members see and
control only those printers. Every other printer answers 404, as if it
didn't exist.

- Groups gain restrict_printers and a group_printers table (migration
  for SQLite and Postgres). A user's printers are the union of their
  limited groups. Groups without the flag don't limit anything, a user
  in no limited group keeps every printer, and admins see all of them.
- core/printer_scope.py holds the scope. RequestPrinterScope and
  RequirePrinterPermissionIfAuthEnabled apply it to routes: printer
  routes, camera, queue and batches, archives, projects, stats, print
  log, pipeline runs, inventory and Spoolman assignments, maintenance,
  smart plugs, scheduled drying, firmware and Obico status.
- API keys, camera stream, Cam Wall, overlay and WebSocket tokens carry
  the printers of whoever created them. WebSocket broadcasts are
  filtered per connection, and the filtering fails closed.
- Scheduler: "Any <model>" jobs stay on their owner's printers. A job
  pinned to a printer its owner lost waits with a reason. Callers with
  no user identity and limited printers must queue to a specific printer.
- Group editor: new Printer access section, translated into all 15
  locales. Saving a system group no longer resends unchanged
  permissions, which the backend refused.
2026-10-01 14:47:40 +02:00
maziggy 89229a5ecc Add group-based permissions system with granular access control
Implement a full permissions system replacing simple admin/user roles:

Backend:
- Add Group model with many-to-many user relationship
- Add 50+ granular permissions (resource:action pattern)
- Create default groups: Administrators, Operators, Viewers
- Add permission-checking dependencies for route protection
- Add groups API endpoints (CRUD, user assignment)
- Add change password endpoint for users
- Update backup/restore to include groups
- Migrate existing users to groups on startup

Frontend:
- Add GroupsPage for managing groups and permissions
- Add permission helpers to AuthContext (hasPermission, hasAnyPermission)
- Add PermissionRoute component for protected routes
- Disable buttons/features based on permissions (with tooltips)
- Add change password modal in sidebar for all users
- Add forgot password info modal on login page
- Show user groups in UsersPage with group assignment

Testing:
- Add integration tests for groups API
- Add tests for user-group assignments
- Add tests for change password endpoint
- Seed default groups in test fixtures

Closes #28 #161
2026-01-31 12:50:15 +01:00