feat: implement 8 OpenSpec proposals for security, reliability, and UX improvements
## Security Enhancements (P0) - Add input validation with max_length and numeric range constraints - Implement WebSocket token authentication via first message - Add path traversal prevention in file storage service ## Permission Enhancements (P0) - Add project member management for cross-department access - Implement is_department_manager flag for workload visibility ## Cycle Detection (P0) - Add DFS-based cycle detection for task dependencies - Add formula field circular reference detection - Display user-friendly cycle path visualization ## Concurrency & Reliability (P1) - Implement optimistic locking with version field (409 Conflict on mismatch) - Add trigger retry mechanism with exponential backoff (1s, 2s, 4s) - Implement cascade restore for soft-deleted tasks ## Rate Limiting (P1) - Add tiered rate limits: standard (60/min), sensitive (20/min), heavy (5/min) - Apply rate limits to tasks, reports, attachments, and comments ## Frontend Improvements (P1) - Add responsive sidebar with hamburger menu for mobile - Improve touch-friendly UI with proper tap target sizes - Complete i18n translations for all components ## Backend Reliability (P2) - Configure database connection pool (size=10, overflow=20) - Add Redis fallback mechanism with message queue - Add blocker check before task deletion ## API Enhancements (P3) - Add standardized response wrapper utility - Add /health/ready and /health/live endpoints - Implement project templates with status/field copying ## Tests Added - test_input_validation.py - Schema and path traversal tests - test_concurrency_reliability.py - Optimistic locking and retry tests - test_backend_reliability.py - Connection pool and Redis tests - test_api_enhancements.py - Health check and template tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,22 +41,34 @@ def check_workload_access(
|
||||
"""
|
||||
Check if current user has access to view workload data.
|
||||
|
||||
Access rules:
|
||||
- System admin: can access all workloads
|
||||
- Department manager: can access workloads of users in their department
|
||||
- Regular user: can only access their own workload
|
||||
|
||||
Raises HTTPException if access is denied.
|
||||
"""
|
||||
# System admin can access all
|
||||
if current_user.is_system_admin:
|
||||
return
|
||||
|
||||
# If querying specific user, must be self
|
||||
# (Phase 1: only self access for non-admin users)
|
||||
# If querying specific user
|
||||
if target_user_id and target_user_id != current_user.id:
|
||||
# Department manager can view subordinates' workload
|
||||
if current_user.is_department_manager:
|
||||
# Manager can view users in their department
|
||||
# target_user_department_id must be provided for this check
|
||||
if target_user_department_id and target_user_department_id == current_user.department_id:
|
||||
return
|
||||
# Access denied for non-manager or user not in same department
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Access denied: Cannot view other users' workload",
|
||||
)
|
||||
|
||||
# If querying by department, must be same department
|
||||
# If querying by department
|
||||
if department_id and department_id != current_user.department_id:
|
||||
# Department manager can only query their own department
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Access denied: Cannot view other departments' workload",
|
||||
@@ -66,15 +78,40 @@ def check_workload_access(
|
||||
def filter_accessible_users(
|
||||
current_user: User,
|
||||
user_ids: Optional[List[str]] = None,
|
||||
db: Optional[Session] = None,
|
||||
) -> Optional[List[str]]:
|
||||
"""
|
||||
Filter user IDs to only those accessible by current user.
|
||||
Returns None if user can access all (system admin).
|
||||
|
||||
Access rules:
|
||||
- System admin: can see all users
|
||||
- Department manager: can see all users in their department
|
||||
- Regular user: can only see themselves
|
||||
"""
|
||||
# System admin can access all
|
||||
if current_user.is_system_admin:
|
||||
return user_ids
|
||||
|
||||
# Department manager can see all users in their department
|
||||
if current_user.is_department_manager and current_user.department_id and db:
|
||||
# Get all users in the same department
|
||||
department_users = db.query(User.id).filter(
|
||||
User.department_id == current_user.department_id,
|
||||
User.is_active == True
|
||||
).all()
|
||||
department_user_ids = {u.id for u in department_users}
|
||||
|
||||
if user_ids:
|
||||
# Filter to only users in manager's department
|
||||
accessible = [uid for uid in user_ids if uid in department_user_ids]
|
||||
if not accessible:
|
||||
return [current_user.id]
|
||||
return accessible
|
||||
else:
|
||||
# No filter specified, return all department users
|
||||
return list(department_user_ids)
|
||||
|
||||
# Regular user can only see themselves
|
||||
if user_ids:
|
||||
# Filter to only accessible users
|
||||
@@ -111,6 +148,11 @@ async def get_heatmap(
|
||||
"""
|
||||
Get workload heatmap for users.
|
||||
|
||||
Access Rules:
|
||||
- System admin: Can view all users' workload
|
||||
- Department manager: Can view workload of all users in their department
|
||||
- Regular user: Can only view their own workload
|
||||
|
||||
Returns workload summaries for users showing:
|
||||
- allocated_hours: Total estimated hours from tasks due this week
|
||||
- capacity_hours: User's weekly capacity
|
||||
@@ -126,8 +168,8 @@ async def get_heatmap(
|
||||
if department_id:
|
||||
check_workload_access(current_user, department_id=department_id)
|
||||
|
||||
# Filter user_ids based on access
|
||||
accessible_user_ids = filter_accessible_users(current_user, parsed_user_ids)
|
||||
# Filter user_ids based on access (pass db for manager department lookup)
|
||||
accessible_user_ids = filter_accessible_users(current_user, parsed_user_ids, db)
|
||||
|
||||
# Normalize week_start
|
||||
if week_start is None:
|
||||
@@ -181,12 +223,25 @@ async def get_user_workload(
|
||||
"""
|
||||
Get detailed workload for a specific user.
|
||||
|
||||
Access rules:
|
||||
- System admin: can view any user's workload
|
||||
- Department manager: can view workload of users in their department
|
||||
- Regular user: can only view their own workload
|
||||
|
||||
Returns:
|
||||
- Workload summary (same as heatmap)
|
||||
- List of tasks contributing to the workload
|
||||
"""
|
||||
# Check access
|
||||
check_workload_access(current_user, target_user_id=user_id)
|
||||
# Get target user's department for manager access check
|
||||
target_user = db.query(User).filter(User.id == user_id).first()
|
||||
target_user_department_id = target_user.department_id if target_user else None
|
||||
|
||||
# Check access (pass target user's department for manager check)
|
||||
check_workload_access(
|
||||
current_user,
|
||||
target_user_id=user_id,
|
||||
target_user_department_id=target_user_department_id
|
||||
)
|
||||
|
||||
# Calculate workload detail
|
||||
detail = get_user_workload_detail(db, user_id, week_start)
|
||||
|
||||
Reference in New Issue
Block a user