Spaces:
Sleeping
Sleeping
File size: 5,510 Bytes
295cd3a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# User Preferences Update Bug - Root Cause & Fix
## Issue Summary
User preferences updates (theme, favorite_apps) were not being saved to the database despite the API returning 200 OK responses.
## Root Cause
### Duplicate Route Definitions
The `auth.py` file had **TWO different endpoints** with the **same route path**:
1. **OLD Endpoint (Line 847)** - `PUT /me/preferences`
- Function: `update_user_preferences()`
- Input: Generic `dict`
- Output: `UserProfile` (no preference fields)
- **Only handled**: `last_active_project_id`
- **Ignored**: `theme`, `favorite_apps`, and all other preference fields
2. **NEW Endpoint (Line 1242)** - `PUT /me/preferences`
- Function: `update_my_preferences()`
- Input: `UserPreferencesUpdate` schema
- Output: `UserPreferencesResponse` (includes all preference fields)
- **Handles**: `favorite_apps`, `theme`, `language`, notifications, etc.
### Why It Failed
When FastAPI registers routes, **only the first matching route is registered**. The old endpoint (line 847) was being called for all `/me/preferences` PUT requests, which:
- Accepted the request body as a dict
- Only looked for `last_active_project_id`
- **Silently ignored** `theme`, `favorite_apps`, and other fields
- Returned `UserProfile` without preference data
- This is why the browser console showed: `favoriteAppsCount: 0, favoriteAppsJson: undefined`
## Evidence from Logs
### Browser Console (browserconsole.txt)
```
Line 48: [DATA] Updating user preferences {theme: 'light', favoriteAppsJson: undefined}
Line 49: PUT https://kamau1-swiftops-backend.hf.space/api/v1/auth/me/preferences
Line 50: PUT .../api/v1/auth/me/preferences β 200 (625ms)
Line 51: [DATA] User preferences updated successfully {updatedFields: Array(1), theme: undefined, favoriteAppsCount: 0, favoriteAppsJson: undefined}
```
The request succeeded (200 OK) but the response didn't contain the updated data.
### Server Logs (runtimeerror.txt)
```
Line 35: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Line 181: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Line 260: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Line 264: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
```
Multiple successful requests, but the old endpoint was being called.
## The Fix
### Changes Made
**1. Added `last_active_project_id` to `UserPreferencesUpdate` schema**
- File: `src/app/schemas/user_preferences.py`
- Added the field so the preferences endpoint can handle project context updates
**2. Enhanced the preferences endpoint with project validation**
- File: `src/app/api/v1/auth.py` (line 1242+)
- Added validation logic for `last_active_project_id`:
- Prevents platform admins from setting project context
- Verifies user is assigned to the project
- Verifies project exists and is active
- Updated field exclusion list to skip validated fields
**3. Removed the old duplicate endpoint entirely**
- File: `src/app/api/v1/auth.py` (previously line 847-1020)
- **Deleted** the old `PUT /me/active-project` endpoint
- No longer needed since the new endpoint handles everything
### Result: Single Unified Endpoint
Now there is **ONE endpoint** that handles **ALL** user preference updates:
**`PUT /api/v1/auth/me/preferences`**
- Input: `UserPreferencesUpdate` schema
- Output: `UserPreferencesResponse`
- Handles:
- β
`favorite_apps` - Array of app codes (max 6, role-validated)
- β
`theme` - 'light', 'dark', or 'auto'
- β
`language` - Language code
- β
`last_active_project_id` - Project context (validated)
- β
`email_notifications` - Boolean
- β
`push_notifications` - Boolean
- β
`sms_notifications` - Boolean
- β
`dashboard_widgets` - Array of widget codes
- β
`default_tickets_view` - 'list', 'kanban', or 'calendar'
- β
All other preference fields
### Response Format
The endpoint now returns `UserPreferencesResponse` which includes:
```json
{
"id": "uuid",
"user_id": "uuid",
"favorite_apps": ["dashboard", "organizations", "users", "activity"],
"theme": "light",
"language": "en",
"email_notifications": true,
"last_active_project_id": "uuid",
...
}
```
## Testing Required
1. **Restart the backend server** to load the updated route
2. **Test theme updates**:
- Toggle theme from dark to light
- Verify database `user_preferences.theme` column updates
- Verify API response contains updated theme
3. **Test favorite apps updates**:
- Add/remove favorite apps
- Verify database `user_preferences.favorite_apps` column updates
- Verify API response contains updated favorite_apps array
4. **Test project context updates**:
- Switch active project
- Verify database `user_preferences.last_active_project_id` column updates
- Verify API response contains updated project ID
## Migration Notes
### Breaking Changes
- **Removed**: `PUT /me/active-project` endpoint (was never in production)
- **Use instead**: `PUT /me/preferences` for all preference updates
### Unified Endpoint
- **Route**: `PUT /api/v1/auth/me/preferences`
- **Purpose**: Update all user preferences in one place
- **Supports**: All preference fields including `last_active_project_id`
## Database Schema
The fix doesn't require any database changes. The `user_preferences` table already has all the necessary columns:
- `favorite_apps` (JSONB array)
- `theme` (VARCHAR)
- `language` (VARCHAR)
- `email_notifications` (BOOLEAN)
- etc.
The issue was purely in the routing layer.
|