Spaces:
Sleeping
UserId Mismatch Debug Analysis
Problem Description
- User ID 25 enrolls β DB shows userId 11
- User ID 25 enrolls again β DB shows userId 12 (incremented by 1)
- User ID 25 enrolls again β DB shows userId 13 (incremented by 1)
Pattern: First enrollment gets a random ID, subsequent enrollments increment by 1
Root Cause Analysis
Hypothesis 1: JWT Payload Contains Wrong UserId β
- Auth service creates payload:
{ sub: user.userId, ... } - JWT Strategy validates:
userId: payload.sub - JWT payload is correct β
Hypothesis 2: Controller Extracts Wrong UserId β LIKELY
File: src/modules/enrollments/controllers/enrollments.controller.ts
@Post('register')
@Roles(RoleName.STUDENT)
async enrollCourse(
@Request() req,
@Body() enrollCourseDto: EnrollCourseDto,
): Promise<EnrollmentResponseDto> {
return this.enrollmentsService.enrollStudent(req.user.userId, enrollCourseDto);
// ^^^^^^ THIS IS WRONG
}
The Real Issue: User Entity Property Name
The problem is likely that req.user object has a different property name than userId.
Common issues:
req.user.idinstead ofreq.user.userIdreq.user.subfrom JWT payload instead ofreq.user.userIdreq.useris the User entity with database columnuser_idbut propertyuserId
Check: What Properties Does req.user Have?
Looking at JWT strategy's validate() method (line 43):
return user; // Returns full User entity object
The User entity has:
@PrimaryGeneratedColumn({ name: 'user_id' })
userId: number; // TypeORM property name
So req.user.userId should work... UNLESS
The Real Problem: Multiple Calls Creating Different Users! π΄
Pattern observed:
- 1st enrollment: userId becomes 11
- 2nd enrollment: userId becomes 12
- 3rd enrollment: userId becomes 13
This looks like req.user is not the user entity, but something else is being auto-incremented.
Possible explanations:
req.user.userIdis undefined β defaults to undefined or null- Auto-increment is being triggered for a related table
- Session table
userIdis being used instead (which is auto-increment)
Most Likely: req.user.id vs req.user.userId
Passport typically returns req.user with the returned object from validate().
The validate() returns the User entity, but Passport might transform it.
Check the exact property name that JWT strategy is returning.
Solution
Add debugging to controller to check what req.user contains:
@Post('register')
@Roles(RoleName.STUDENT)
async enrollCourse(
@Request() req,
@Body() enrollCourseDto: EnrollCourseDto,
): Promise<EnrollmentResponseDto> {
console.log('req.user:', req.user); // Debug
console.log('req.user properties:', Object.keys(req.user)); // Show all keys
console.log('req.user.userId:', req.user.userId); // Check this value
console.log('req.user.id:', req.user.id); // Check this too
return this.enrollmentsService.enrollStudent(req.user.userId, enrollCourseDto);
}
Likely Fixes
Fix 1: Use req.user.id instead of req.user.userId
// Change this:
return this.enrollmentsService.enrollStudent(req.user.userId, enrollCourseDto);
// To this:
return this.enrollmentsService.enrollStudent(req.user.id, enrollCourseDto);
Fix 2: Check if userId is null and handle
const userId = req.user.userId || req.user.id;
if (!userId) {
throw new BadRequestException('User ID not found in token');
}
return this.enrollmentsService.enrollStudent(userId, enrollCourseDto);
Fix 3: Check JWT Strategy's validate method
Make sure it returns the correct user object with userId property.
Files to Check
- src/modules/auth/strategies/jwt.strategy.ts - Line 43 (return user)
- src/modules/enrollments/controllers/enrollments.controller.ts - Line 63 (req.user.userId)
- src/modules/auth/entities/user.entity.ts - Verify userId property
Next Steps
- Add console.log statements to debug
- Check what
req.useractually contains - Verify the property name matches
- Fix in all enrollment controller methods
- Test enrollment again