What happened?
joinQuizController in apps/http-server/src/controllers/sessionController.ts
stores the participant's user id:
const participant = await tx.participant.create({
data: {
username,
sessionId: session.id,
userId: req.userId || null
}
});
But the route has no authMiddleware:
apps/http-server/src/routes/session.ts:
router.post("/join", joinQuizController)
req.userId is only ever set by authMiddleware, so it is always
undefined here, and every participant row is written with userId: null —
including participants who are signed in.
Why it matters. planning.md promises that a registered user can see the
quizzes they participated in. getAllQuizesController cannot deliver that,
because nothing connects a Participant row to a User. The feature is
silently broken.
The tricky part. Joining must stay open to anonymous participants — that is
a core feature, no signup required to play. So this cannot simply have
authMiddleware bolted on, which would reject anonymous joins with a 401.
What is needed is optional authentication: attach req.userId when a valid
token is present, and continue without it otherwise.
Steps to reproduce
Suggested fix. Add an optionalAuth middleware next to the existing one in
apps/http-server/src/middlewares/authmiddleware.ts:
- No
Authorization header → call next() with no req.userId
- Valid token → set
req.userId, call next()
- Malformed or expired token → also just
next() without req.userId, so a
stale token in someone's browser does not block them from joining a quiz
Then apply it to POST /join.
Definition of done:
- A signed-in user who joins gets a
Participant row with their userId
- An anonymous user can still join with no token at all
- An expired token does not prevent joining
- Participation history works for registered users
Which part of Rexial?
http-server (Express REST API)
How are you running Rexial?
Docker Compose (docker-compose up)
Logs or error output
Environment
No response
Before submitting
What happened?
joinQuizControllerinapps/http-server/src/controllers/sessionController.tsstores the participant's user id:
But the route has no
authMiddleware:apps/http-server/src/routes/session.ts:req.userIdis only ever set byauthMiddleware, so it is alwaysundefinedhere, and every participant row is written withuserId: null—including participants who are signed in.
Why it matters.
planning.mdpromises that a registered user can see thequizzes they participated in.
getAllQuizesControllercannot deliver that,because nothing connects a
Participantrow to aUser. The feature issilently broken.
The tricky part. Joining must stay open to anonymous participants — that is
a core feature, no signup required to play. So this cannot simply have
authMiddlewarebolted on, which would reject anonymous joins with a 401.What is needed is optional authentication: attach
req.userIdwhen a validtoken is present, and continue without it otherwise.
Steps to reproduce
Suggested fix. Add an
optionalAuthmiddleware next to the existing one inapps/http-server/src/middlewares/authmiddleware.ts:Authorizationheader → callnext()with noreq.userIdreq.userId, callnext()next()withoutreq.userId, so astale token in someone's browser does not block them from joining a quiz
Then apply it to
POST /join.Definition of done:
Participantrow with theiruserIdWhich part of Rexial?
http-server (Express REST API)
How are you running Rexial?
Docker Compose (docker-compose up)
Logs or error output
Environment
No response
Before submitting