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.