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
- _Requirements: 6.3, 6.4, 6.5_
- [-] 16. Implement notification preferences
- [x] 16. Implement notification preferences
- Create notification settings interface
- Build area of interest selector with map
- Implement radius configuration (1-50km)

View File

@@ -54,20 +54,40 @@ export class UserController {
});
}
// Find or create user to get database ID
const dbUserId = await userService.findOrCreateUser(req.userId);
if (dbUserId !== id) {
return res.status(403).json({
error: {
code: 'FORBIDDEN',
message: 'You can only update your own profile',
timestamp: new Date().toISOString(),
},
});
// Check if the ID in the URL is a Clerk ID or database ID
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) {
return res.status(403).json({
error: {
code: 'FORBIDDEN',
message: 'You can only update your own profile',
timestamp: new Date().toISOString(),
},
});
}
}
const updatedProfile = await userService.updateUserProfile(id, {
const updatedProfile = await userService.updateUserProfile(dbUserId, {
firstName,
lastName,
username,
@@ -168,17 +188,38 @@ export class UserController {
});
}
// Find or create user to get database ID
const dbUserId = await userService.findOrCreateUser(req.userId);
if (dbUserId !== id) {
return res.status(403).json({
error: {
code: 'FORBIDDEN',
message: 'You can only update your own preferences',
timestamp: new Date().toISOString(),
},
});
// Check if the ID in the URL is a Clerk ID or database ID
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) {
return res.status(403).json({
error: {
code: 'FORBIDDEN',
message: 'You can only update your own preferences',
timestamp: new Date().toISOString(),
},
});
}
}
// Validate areasOfInterest if provided
@@ -216,7 +257,7 @@ export class UserController {
}
}
const updatedPreferences = await userService.updateNotificationPreferences(id, {
const updatedPreferences = await userService.updateNotificationPreferences(req.params.id, {
notificationEmail,
notificationInApp,
areasOfInterest,