Skip to content

Commit 9cb7ff4

Browse files
committed
Merge branch 'n1-comms' into formatting
# Conflicts: # collab/main.go # compose.yaml # nginx/nginx.conf # peerprep/app/questions/[question]/[roomID]/page.tsx # peerprep/app/questions/[question]/[roomID]/question.tsx # peerprep/components/questionpage/CollabEditor.tsx
2 parents 367f010 + 2838af0 commit 9cb7ff4

File tree

36 files changed

+2253
-113
lines changed

36 files changed

+2253
-113
lines changed

collab/main.go

Lines changed: 92 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"os"
1010
"sync"
11+
"strconv"
1112

1213
"github.com/gin-gonic/gin"
1314
"github.com/gorilla/websocket"
@@ -142,8 +143,11 @@ func (h *Hub) Run() {
142143
}
143144

144145
// ServeWs handles WebSocket requests
145-
func serveWs(hub *Hub, c *gin.Context, roomMappings *verify.RoomMappings) {
146-
146+
func serveWs(
147+
hub *Hub, c *gin.Context,
148+
roomMappings *verify.RoomMappings,
149+
persistMappings *verify.PersistMappings,
150+
) {
147151
log.Println("handler called!")
148152
roomID := c.Query("roomID")
149153
if roomID == "" {
@@ -160,20 +164,40 @@ func serveWs(hub *Hub, c *gin.Context, roomMappings *verify.RoomMappings) {
160164
client := &Client{conn: conn, roomID: roomID}
161165
hub.register <- client
162166

163-
go handleMessages(client, hub, roomMappings)
167+
go handleMessages(client, hub, roomMappings, persistMappings)
168+
}
169+
170+
func authenticateClient(
171+
token string, match string, client *Client,
172+
roomMappings *verify.RoomMappings,
173+
persistMappings *verify.PersistMappings,
174+
) bool {
175+
ok, userID := verifyToken(token)
176+
if !ok {
177+
log.Println("bad token in request")
178+
return false
179+
}
180+
return verify.VerifyRoomAndMoveToPersist(
181+
roomMappings, client.roomID, userID, match, persistMappings)
164182
}
165183

166-
func authenticateClient(token string, client *Client, roomMappings *verify.RoomMappings) bool {
184+
func authenticateClientNoMatch(
185+
token string, client *Client,
186+
persistMappings *verify.PersistMappings,
187+
) bool {
167188
ok, userID := verifyToken(token)
168189
if !ok {
169-
log.Println("bruh")
190+
log.Println("bad token in request")
170191
return false
171192
}
172-
return verify.VerifyRoom(roomMappings, client.roomID, userID)
193+
return verify.VerifyPersist(persistMappings, client.roomID, userID)
173194
}
174195

175-
func handleMessages(client *Client, hub *Hub, roomMappings *verify.RoomMappings) {
176-
defer func() {
196+
func handleMessages(
197+
client *Client, hub *Hub,
198+
roomMappings *verify.RoomMappings,
199+
persistMappings *verify.PersistMappings,
200+
) { defer func() {
177201
hub.unregister <- client
178202
}()
179203

@@ -189,12 +213,36 @@ func handleMessages(client *Client, hub *Hub, roomMappings *verify.RoomMappings)
189213
log.Printf("Failed to parse message: %v", err)
190214
continue
191215
}
192-
// Handle authentication message
193216
if msgData["type"] == "auth" {
194-
token, ok := msgData["token"].(string)
195-
if !ok || !authenticateClient(token, client, roomMappings) {
196-
log.Println("Authentication failed")
197-
client.conn.WriteMessage(websocket.TextMessage, []byte("Authentication failed"))
217+
token, tokenOk := msgData["token"].(string)
218+
if !tokenOk {
219+
log.Println("Authentication failed - no token attached")
220+
client.conn.WriteMessage(
221+
websocket.TextMessage,
222+
[]byte("Authentication failed - no JWT token"),
223+
)
224+
client.conn.Close()
225+
break
226+
}
227+
isSuccess := false
228+
match, matchOk := msgData["matchHash"].(string)
229+
if matchOk && !authenticateClient(token, match, client, roomMappings, persistMappings) {
230+
log.Println(
231+
"failed to find a matching room from match hash, proceeding with persistence check",
232+
)
233+
}
234+
// I will ping the persistent map even if I've found it in the original map
235+
if !authenticateClientNoMatch(token, client, persistMappings) {
236+
log.Println("failed to find a persistent room")
237+
isSuccess = false
238+
} else {
239+
isSuccess = true
240+
}
241+
if !isSuccess {
242+
client.conn.WriteMessage(
243+
websocket.TextMessage,
244+
[]byte("Authentication failed - failed to find a matching room"),
245+
)
198246
client.conn.Close()
199247
break
200248
}
@@ -226,14 +274,14 @@ func statusHandler(hub *Hub) gin.HandlerFunc {
226274
for client := range hub.clients {
227275
roomID := client.roomID
228276
currentStatus, ok := status[roomID]
229-
if !ok {
230-
// Initialize status for a new RoomID
277+
if (!ok) {
278+
// Initialize status for a new roomID
231279
status[roomID] = map[string]interface{}{
232-
"clients": 1,
233-
"workspace": hub.workspaces[roomID],
280+
"clients": 1,
281+
"workspace": hub.workspaces[roomID],
234282
}
235283
} else {
236-
// Update the client count for an existing RoomID
284+
// Update the client count for an existing roomID
237285
status[roomID] = map[string]interface{}{
238286
"clients": currentStatus.(map[string]interface{})["clients"].(int) + 1,
239287
"workspace": hub.workspaces[roomID],
@@ -254,10 +302,34 @@ func main() {
254302
if REDIS_URI == "" {
255303
REDIS_URI = "localhost:9190"
256304
}
257-
roomMappings := verify.InitialiseRoomMappings(REDIS_URI, 1)
305+
306+
REDIS_ROOM_MAPPING := 1
307+
REDIS_ROOM_PERSIST := 2
308+
309+
if os.Getenv("REDIS_ROOM_MAPPING") != "" {
310+
num, err := strconv.Atoi(os.Getenv("REDIS_ROOM_MAPPING"))
311+
if err != nil {
312+
log.Fatal("DB no of room map is badly formatted" + err.Error())
313+
} else {
314+
REDIS_ROOM_MAPPING = num
315+
}
316+
}
317+
318+
if os.Getenv("REDIS_ROOM_PERSIST") != "" {
319+
num, err := strconv.Atoi(os.Getenv("REDIS_ROOM_PERSIST"))
320+
if err != nil {
321+
log.Fatal("DB no of room persistance store is badly formatted" + err.Error())
322+
} else {
323+
REDIS_ROOM_PERSIST = num
324+
}
325+
}
326+
327+
roomMappings := verify.InitialiseRoomMappings(REDIS_URI, REDIS_ROOM_MAPPING)
328+
persistMappings := verify.InitialisePersistMappings(REDIS_URI, REDIS_ROOM_PERSIST);
329+
258330
// WebSocket connection endpoint
259331
r.GET("/ws", func(c *gin.Context) {
260-
serveWs(hub, c, roomMappings)
332+
serveWs(hub, c, roomMappings, persistMappings)
261333
})
262334

263335
// Status endpoint

collab/verify/persistMappings.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package verify
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
redis "github.com/go-redis/redis/v8"
8+
)
9+
10+
// same as room mappings, but separated for type safety
11+
type PersistMappings struct {
12+
Conn *redis.Client
13+
}
14+
15+
func InitialisePersistMappings(addr string, db_num int) *PersistMappings {
16+
conn := redis.NewClient(&redis.Options{
17+
Addr: addr,
18+
DB: db_num,
19+
})
20+
21+
return &PersistMappings{
22+
Conn: conn,
23+
}
24+
}
25+
26+
func VerifyPersist(persistMappings *PersistMappings, roomID string, userID string) bool {
27+
data, err := persistMappings.Conn.HGetAll(context.Background(), userID).Result()
28+
if err != nil {
29+
log.Printf("Error retrieving data for userID %s: %v", userID, err)
30+
return false
31+
}
32+
33+
return data["roomId"] == roomID
34+
}

collab/verify/roomMappings.go

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,44 @@ func InitialiseRoomMappings(addr string, db_num int) *RoomMappings {
2323
}
2424
}
2525

26-
func VerifyRoom(roomMappings *RoomMappings, roomID string, userID string) bool {
27-
data, err := roomMappings.Conn.HGetAll(context.Background(), userID).Result()
26+
func VerifyRoomAndMoveToPersist(
27+
roomMappings *RoomMappings,
28+
roomID string,
29+
userId string,
30+
matchHash string,
31+
persistMappings *PersistMappings,
32+
) bool {
33+
ctx := context.Background()
34+
data, err := roomMappings.Conn.HGetAll(ctx, matchHash).Result()
2835
if err != nil {
29-
log.Printf("Error retrieving data for userID %s: %v", userID, err)
36+
log.Printf("Error retrieving data for matchHash %s: %v", matchHash, err)
3037
return false
3138
}
3239

33-
return data["roomId"] == roomID
40+
if data["roomId"] != roomID || data["thisUser"] != userId {
41+
log.Printf("Mismatch in room data and user data")
42+
return false
43+
}
44+
45+
roomMappings.Conn.Del(ctx, matchHash);
46+
persistentRoom := map[string]interface{}{
47+
"roomId": roomID,
48+
"otherUser": data["otherUser"],
49+
"requestTime": data["requestTime"],
50+
51+
"title": data["title"],
52+
"titleSlug": data["titleSlug"],
53+
"difficulty": data["difficulty"],
54+
"topicTags": data["topicTags"],
55+
"content": data["content"],
56+
"schemas": data["schemas"],
57+
"id": data["id"],
58+
}
59+
60+
// this always overrides the persistent room
61+
if err := persistMappings.Conn.HSet(ctx, userId, persistentRoom).Err(); err != nil {
62+
log.Printf("error sending room to persistent storage: %s", err.Error())
63+
}
64+
65+
return true
3466
}

comms/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FRONTEND=

comms/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
.env

comms/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM node:lts-alpine3.20
2+
3+
WORKDIR /comms
4+
COPY package*.json ./
5+
RUN npm install --force
6+
COPY . .
7+
EXPOSE 4001
8+
CMD ["npm", "run", "dev"]

0 commit comments

Comments
 (0)