@@ -324,9 +324,45 @@ Future<Response> _handlePut(
324324 case 'user' :
325325 {
326326 final repo = context.read <DataRepository <User >>();
327+ 328+ // --- Safe User Update Logic ---
329+ // To prevent security vulnerabilities like privilege escalation, we do not
330+ // simply save the entire request body. Instead, we perform a safe,
331+ // partial update.
332+ 333+ // 1. Fetch the existing, trusted user object from the database.
334+ // This ensures we have the current, authoritative state of the user,
335+ // including their correct roles and ID.
336+ final existingUser = await repo.read (
337+ id: id,
338+ userId: userIdForRepoCall,
339+ );
340+ 341+ // 2. Create a new User object by merging only the allowed, safe-to-update
342+ // fields from the incoming request (`itemToUpdate`) into the
343+ // existing user data.
344+ // This is the most critical step. It guarantees that a user cannot
345+ // change their own `appRole`, `dashboardRole`, `id`, or `createdAt`
346+ // fields, even if they include them in the request payload.
347+ // The `email` field is also protected here, as changing it requires a
348+ // separate, secure verification flow (e.g., via a dedicated endpoint)
349+ // and should not be done through this generic data endpoint.
350+ final updatedUser = existingUser.copyWith (
351+ // `feedActionStatus` is considered safe for a user to update as it
352+ // only tracks their interaction with UI elements.
353+ feedActionStatus: (itemToUpdate as User ).feedActionStatus,
354+ 355+ // FUTURE: If a `displayName` field were added to the User model,
356+ // it would also be considered safe and could be updated here:
357+ // displayName: itemToUpdate.displayName,
358+ );
359+ 360+ // 3. Save the securely merged user object back to the database.
361+ // The repository will now update the user record with our safely
362+ // constructed `updatedUser` object.
327363 updatedItem = await repo.update (
328364 id: id,
329- item: itemToUpdate as User ,
365+ item: updatedUser ,
330366 userId: userIdForRepoCall,
331367 );
332368 }
0 commit comments