Skip to content

Hebe/msg persistence - #72

Merged
Duckierstone42 merged 6 commits into
mainfrom
hebe/msg-persistence
Apr 10, 2026
Merged

Duckierstone42 merged 6 commits into
mainfrom
hebe/msg-persistence

Conversation

@Hebe3834

Copy link
Copy Markdown
Collaborator

Addresses #35

@netlify

netlify Bot commented Apr 10, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for able-alliance ready!

Name Link
🔨 Latest commit 6d5c70f
🔍 Latest deploy log https://app.netlify.com/projects/able-alliance/deploys/69d988aafd8fd30008e89c8c
😎 Deploy Preview https://deploy-preview-72--able-alliance.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@greptile-apps

greptile-apps Bot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds chat message persistence for socket-based routes: messages are stored in an in-memory chatStore during an active ride and flushed to a chatlogs MongoDB collection when endRoute is called. The test page is updated to fetch a real route from the DB rather than using a hardcoded ID.

  • P1 — event name mismatch: the server emits \"routeClosed\" but the client listens for \"routeEnded\", so clients never receive the route-end signal.
  • P1 — hardcoded SuperAdmin ObjectId in endRoute (\"69d8392ed589ac8dd451ce65\") inconsistently replaces the role-based check (decoded.type === \"SuperAdmin\") used in the auth middleware; other SuperAdmins will be incorrectly blocked.

Confidence Score: 4/5

Two P1 bugs need fixing before merge: the routeClosed/routeEnded event name mismatch silently breaks client notification, and the hardcoded SuperAdmin ObjectId breaks role-based access for all other super admins.

Both P1 findings are present defects on the changed code path — the event name mismatch means clients never get notified when a route ends, and the hardcoded ID means SuperAdmin access control is broken for anyone other than one specific user. Remaining findings are P2 cleanup items that don't block merge.

websocket-server/index.mjs — both P1 issues are in this file.

Important Files Changed

Filename Overview
websocket-server/index.mjs Adds in-memory chat history (chatStore), per-message DB lookup for sender type, and endRoute handler — but has a P1 event name mismatch (routeClosed vs routeEnded) and a hardcoded SuperAdmin ObjectId instead of role-based check.
src/app/socket-test/page.tsx Test page updated to fetch route from DB dynamically and expose chat/location/endRoute controls; contains console.logs and
spacers expected for a dev test page.
scripts/seed.ts Adds a SuperAdmin route template to seed data to support testing the new endRoute permission; straightforward change.
docker-compose.yml Mounts ./scripts into the container so seed scripts can be run inside Docker; safe change.

Sequence Diagram

sequenceDiagram
    participant C as Client
    participant WS as WebSocket Server
    participant Store as chatStore (in-memory)
    participant DB as MongoDB

    C->>WS: connect (routeId, token)
    WS->>DB: getRouteForAuth(routeId)
    DB-->>WS: route document
    WS->>Store: get(routeId) → history
    WS-->>C: emit("chatHistory", history)

    C->>WS: emit("sendChatMessage", text)
    WS->>DB: getRouteForAuth(routeId) [per message]
    DB-->>WS: route document (for senderType)
    WS->>Store: push message
    WS-->>C: emit("receiveChatMessage", message) [broadcast to room]

    C->>WS: emit("endRoute")
    WS->>DB: getRouteForAuth(routeId)
    DB-->>WS: route document
    WS->>Store: get(routeId) → messages
    WS->>DB: chatlogs.insertOne({routeId, messages, ...})
    WS->>Store: delete(routeId)
    WS-->>C: emit("routeClosed") ⚠️ client expects "routeEnded"
    WS->>C: disconnect()
Loading

Reviews (1): Last reviewed commit: "testing in frontend" | Re-trigger Greptile

console.log("Chat log content:" + JSON.stringify(messages)); //TESTING

chatStore.delete(routeId);
io.to(room).emit("routeClosed");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Event name mismatch — client never receives route-end notification

The server emits "routeClosed" but the client in socket-test/page.tsx (line 71) listens for "routeEnded". These names don't match, so the client will silently never receive the signal when a route ends.

Suggested change
io.to(room).emit("routeClosed");
io.to(room).emit("routeEnded");

Comment on lines +192 to +194
const isDriver = route.driver?._id?.toString() === socket.user;
const isSuperAdmin = socket.user === "69d8392ed589ac8dd451ce65";
if (!isDriver && !isSuperAdmin) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Hardcoded SuperAdmin ObjectId is fragile and inconsistent

The auth middleware correctly uses decoded.type === "SuperAdmin" (line 110) to identify super admins, but the endRoute handler hardcodes a specific ObjectId "69d8392ed589ac8dd451ce65". Any other SuperAdmin user will be blocked from ending routes. Store decoded.type on the socket during auth and reuse it here.

// In auth middleware (after line 116):
socket.userType = decoded.type;

// In endRoute handler:
const isSuperAdmin = socket.userType === "SuperAdmin";

messages,
});
console.log(`Chat log saved for route ${routeId}`);
console.log("Chat log content:" + JSON.stringify(messages)); //TESTING

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Debug console.log with //TESTING comment

This debug line should be removed before merging.

Suggested change
console.log("Chat log content:" + JSON.stringify(messages)); //TESTING

Context Used: Fill out this checklist in addition to code commen... (source)

Comment on lines +144 to +148
const routeId = socket.routeId;
const route = await getRouteForAuth(routeId);
const senderType =
route.driver?._id?.toString() === socket.user
? "driver"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unnecessary DB call per message to determine sender type

getRouteForAuth hits the database on every sendChatMessage event solely to determine whether the sender is a driver or student. This information is already known at connection time. Store senderType on socket during the auth/connection phase and read it here instead.

@Duckierstone42
Duckierstone42 merged commit 8a53b67 into main Apr 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants