Files
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

90 lines
1.7 KiB
Python

"""Pydantic schemas for Group CRUD operations."""
from datetime import datetime
from pydantic import BaseModel
class GroupBrief(BaseModel):
"""Brief group info for embedding in other responses."""
id: int
name: str
class Config:
from_attributes = True
class GroupCreate(BaseModel):
"""Schema for creating a new group."""
name: str
description: str | None = None
permissions: list[str] = []
class GroupUpdate(BaseModel):
"""Schema for updating a group."""
name: str | None = None
description: str | None = None
permissions: list[str] | None = None
class GroupResponse(BaseModel):
"""Schema for group response."""
id: int
name: str
description: str | None
permissions: list[str]
is_system: bool
user_count: int = 0
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class GroupDetailResponse(GroupResponse):
"""Schema for detailed group response including users."""
users: list["UserBrief"] = []
class UserBrief(BaseModel):
"""Brief user info for embedding in group response."""
id: int
username: str
is_active: bool
class Config:
from_attributes = True
class PermissionInfo(BaseModel):
"""Schema for permission information."""
value: str
label: str
class PermissionCategory(BaseModel):
"""Schema for a category of permissions."""
name: str
permissions: list[PermissionInfo]
class PermissionsListResponse(BaseModel):
"""Schema for listing all permissions by category."""
categories: list[PermissionCategory]
all_permissions: list[str]
# Update forward references
GroupDetailResponse.model_rebuild()