Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f33667d

Browse files
authored
Merge pull request #35 from flutter-news-app-full-source-code/enhanceuser-route-put
Enhanceuser route put
2 parents a575011 + 8c05e11 commit f33667d

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

‎lib/src/rbac/role_permissions.dart‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@ final Set<String> _appGuestUserPermissions = {
1414
Permissions.userContentPreferencesReadOwned,
1515
Permissions.userContentPreferencesUpdateOwned,
1616
Permissions.remoteConfigRead,
17+
// Allows a user to update their own User object. This is essential for
18+
// features like updating the `feedActionStatus` (e.g., when a user
19+
// dismisses an in-feed prompt, etc). The endpoint handler ensures only
20+
// non-sensitive fields can be modified.
21+
Permissions.userUpdateOwned,
1722
};
1823

1924
final Set<String> _appStandardUserPermissions = {
2025
..._appGuestUserPermissions,
2126
Permissions.userReadOwned,
22-
Permissions.userUpdateOwned,
2327
Permissions.userDeleteOwned,
2428
};
2529

‎routes/api/v1/data/[id]/index.dart‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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 asUser,
365+
item: updatedUser,
330366
userId: userIdForRepoCall,
331367
);
332368
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /