Fix 403 error in notification preferences and profile updates

- Handle both Clerk ID and database ID in authorization checks
- Compare Clerk IDs when URL parameter is a Clerk ID (user_xxx)
- Convert Clerk ID to database ID for service layer operations
- Apply fix to both updateNotificationPreferences and updateUserProfile endpoints
This commit is contained in:
2025-11-16 22:03:50 +00:00
parent 86169f6141
commit 06c2310266
2 changed files with 66 additions and 25 deletions

View File

@@ -125,7 +125,7 @@
- Add profile editing functionality - Add profile editing functionality
- _Requirements: 6.3, 6.4, 6.5_ - _Requirements: 6.3, 6.4, 6.5_
- [-] 16. Implement notification preferences - [x] 16. Implement notification preferences
- Create notification settings interface - Create notification settings interface
- Build area of interest selector with map - Build area of interest selector with map
- Implement radius configuration (1-50km) - Implement radius configuration (1-50km)

View File

@@ -54,9 +54,28 @@ export class UserController {
}); });
} }
// Find or create user to get database ID // Check if the ID in the URL is a Clerk ID or database ID
const dbUserId = await userService.findOrCreateUser(req.userId); const isClerkId = id.startsWith('user_');
let dbUserId: string;
// If it's a Clerk ID, it should match the authenticated user's Clerk ID
// If it's a database ID, we need to get the database ID for the authenticated user
if (isClerkId) {
// Direct Clerk ID comparison
if (req.userId !== id) {
return res.status(403).json({
error: {
code: 'FORBIDDEN',
message: 'You can only update your own profile',
timestamp: new Date().toISOString(),
},
});
}
// Convert Clerk ID to database ID for the update
dbUserId = await userService.findOrCreateUser(req.userId);
} else {
// Database ID comparison - need to get the database ID for the authenticated user
dbUserId = await userService.findOrCreateUser(req.userId);
if (dbUserId !== id) { if (dbUserId !== id) {
return res.status(403).json({ return res.status(403).json({
error: { error: {
@@ -66,8 +85,9 @@ export class UserController {
}, },
}); });
} }
}
const updatedProfile = await userService.updateUserProfile(id, { const updatedProfile = await userService.updateUserProfile(dbUserId, {
firstName, firstName,
lastName, lastName,
username, username,
@@ -168,9 +188,29 @@ export class UserController {
}); });
} }
// Find or create user to get database ID // Check if the ID in the URL is a Clerk ID or database ID
const dbUserId = await userService.findOrCreateUser(req.userId); const isClerkId = id.startsWith('user_');
// If it's a Clerk ID, it should match the authenticated user's Clerk ID
// If it's a database ID, we need to get the database ID for the authenticated user
if (isClerkId) {
// Direct Clerk ID comparison
if (req.userId !== id) {
return res.status(403).json({
error: {
code: 'FORBIDDEN',
message: 'You can only update your own preferences',
timestamp: new Date().toISOString(),
},
});
}
// Convert Clerk ID to database ID for the update
const dbUserId = await userService.findOrCreateUser(req.userId);
// Update the id variable to use database ID for the service call
req.params.id = dbUserId;
} else {
// Database ID comparison - need to get the database ID for the authenticated user
const dbUserId = await userService.findOrCreateUser(req.userId);
if (dbUserId !== id) { if (dbUserId !== id) {
return res.status(403).json({ return res.status(403).json({
error: { error: {
@@ -180,6 +220,7 @@ export class UserController {
}, },
}); });
} }
}
// Validate areasOfInterest if provided // Validate areasOfInterest if provided
if (areasOfInterest) { if (areasOfInterest) {
@@ -216,7 +257,7 @@ export class UserController {
} }
} }
const updatedPreferences = await userService.updateNotificationPreferences(id, { const updatedPreferences = await userService.updateNotificationPreferences(req.params.id, {
notificationEmail, notificationEmail,
notificationInApp, notificationInApp,
areasOfInterest, areasOfInterest,