diff --git a/backend/collab-service/.env.sample b/backend/collab-service/.env.sample
index 94020b37a8..65939ae031 100644
--- a/backend/collab-service/.env.sample
+++ b/backend/collab-service/.env.sample
@@ -4,6 +4,9 @@ SERVICE_PORT=3003
# Origins for cors
ORIGINS=http://localhost:5173,http://127.0.0.1:5173
+# Other service APIs
+USER_SERVICE_URL=http://user-service:3001/api
+
# Redis configuration
REDIS_URI=redis://collab-service-redis:6379
diff --git a/backend/collab-service/src/api/userService.ts b/backend/collab-service/src/api/userService.ts
new file mode 100644
index 0000000000..88442a3b6c
--- /dev/null
+++ b/backend/collab-service/src/api/userService.ts
@@ -0,0 +1,15 @@
+import axios from "axios";
+
+const USER_SERVICE_URL =
+ process.env.USER_SERVICE_URL || "http://localhost:3001/api";
+
+const userClient = axios.create({
+ baseURL: USER_SERVICE_URL,
+ withCredentials: true,
+});
+
+export const verifyToken = (token: string | undefined) => {
+ return userClient.get("/auth/verify-token", {
+ headers: { authorization: token },
+ });
+};
diff --git a/backend/collab-service/src/middlewares/basicAccessControl.ts b/backend/collab-service/src/middlewares/basicAccessControl.ts
new file mode 100644
index 0000000000..727ee6783e
--- /dev/null
+++ b/backend/collab-service/src/middlewares/basicAccessControl.ts
@@ -0,0 +1,19 @@
+import { ExtendedError, Socket } from "socket.io";
+import { verifyToken } from "../api/userService.ts";
+
+export const verifyUserToken = (
+ socket: Socket,
+ next: (err?: ExtendedError) => void
+) => {
+ const token =
+ socket.handshake.headers.authorization || socket.handshake.auth.token;
+ verifyToken(token)
+ .then(() => {
+ console.log("Valid credentials");
+ next();
+ })
+ .catch((err) => {
+ console.error(err);
+ next(new Error("Unauthorized"));
+ });
+};
diff --git a/backend/collab-service/src/server.ts b/backend/collab-service/src/server.ts
index c1d11c7333..1a00c9c42c 100644
--- a/backend/collab-service/src/server.ts
+++ b/backend/collab-service/src/server.ts
@@ -3,8 +3,10 @@ import app, { allowedOrigins } from "./app.ts";
import { handleWebsocketCollabEvents } from "./handlers/websocketHandler.ts";
import { Server, Socket } from "socket.io";
import { connectRedis } from "./config/redis.ts";
+import { verifyUserToken } from "./middlewares/basicAccessControl.ts";
const server = http.createServer(app);
+
export const io = new Server(server, {
cors: {
origin: allowedOrigins,
@@ -13,6 +15,8 @@ export const io = new Server(server, {
connectionStateRecovery: {},
});
+io.use(verifyUserToken);
+
io.on("connection", (socket: Socket) => {
handleWebsocketCollabEvents(socket);
});
diff --git a/backend/communication-service/.env.sample b/backend/communication-service/.env.sample
index e5f4ba279e..702bd12d55 100644
--- a/backend/communication-service/.env.sample
+++ b/backend/communication-service/.env.sample
@@ -3,3 +3,6 @@ SERVER_PORT=3005
# Origins for cors
ORIGINS=http://localhost:5173,http://127.0.0.1:5173
+
+# Other service APIs
+USER_SERVICE_URL=http://user-service:3001/api
diff --git a/backend/communication-service/README.md b/backend/communication-service/README.md
index b0f30a74e9..f1e24f9098 100644
--- a/backend/communication-service/README.md
+++ b/backend/communication-service/README.md
@@ -30,19 +30,23 @@
- Select the `Socket.IO` option and set URL to `http://localhost:3005`. Click `Connect`.
- ![image1.png](./docs/image1.png)
+ ![image1.png](./docs/images/postman-setup1.png)
- Add the following events in the `Events` tab and listen to them.
- ![image2.png](./docs/image2.png)
+ ![image2.png](./docs/images/postman-setup2.png)
- - To send a message, go to the `Message` tab and ensure that your message is being parsed as `JSON`.
+ - Add a valid JWT token in the `Authorization` header.
- ![image3.png](./docs/image3.png)
+ ![image3.png](./docs/images/postman-setup3.png)
- In the `Event name` input, input the correct event name. Click on `Send` to send a message.
- ![image4.png](./docs/image4.png)
+ ![image4.png](./docs/images/postman-setup4.png)
+
+ - To send a message, go to the `Message` tab and ensure that your message is being parsed as `JSON`.
+
+ ![image5.png](./docs/images/postman-setup5.png)
## Events Available
@@ -50,5 +54,5 @@
| --------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| **join** | Joins a communication rooms | `roomId` (string): ID of the room.
`username` (string): Username of the user that joined. | **user_joined**: Notify the other user that a new user has joined the room. |
| **send_text_message** | Sends a message to the other user | `roomId` (string): ID of the room.
`message` (string): Message to send.
`username` (string): User that sent the message.
`createdTime` (number): Time that the user sent the message. | **text_message_received**: Notify the user that a message is sent |
-| **leave** | Leaves the communication room. | `roomId` (string): ID of the room to leave.
`username` (string): User that wants to leave. | **user_left**: To notify the user when one user leaves. |
+| **user_disconnect** | User disconnection. | None | **user_left**: To notify the user when one user leaves. |
| **disconnect** | Disconnects from the server. | None | **disconnected**: To notify the user when one user gets disconnected from the server. |
diff --git a/backend/communication-service/docs/image2.png b/backend/communication-service/docs/image2.png
deleted file mode 100644
index e422ba0462..0000000000
Binary files a/backend/communication-service/docs/image2.png and /dev/null differ
diff --git a/backend/communication-service/docs/image1.png b/backend/communication-service/docs/images/postman-setup1.png
similarity index 100%
rename from backend/communication-service/docs/image1.png
rename to backend/communication-service/docs/images/postman-setup1.png
diff --git a/backend/communication-service/docs/images/postman-setup2.png b/backend/communication-service/docs/images/postman-setup2.png
new file mode 100644
index 0000000000..d361fb1ce3
Binary files /dev/null and b/backend/communication-service/docs/images/postman-setup2.png differ
diff --git a/backend/communication-service/docs/images/postman-setup3.png b/backend/communication-service/docs/images/postman-setup3.png
new file mode 100644
index 0000000000..3b0a722fdc
Binary files /dev/null and b/backend/communication-service/docs/images/postman-setup3.png differ
diff --git a/backend/communication-service/docs/image4.png b/backend/communication-service/docs/images/postman-setup4.png
similarity index 100%
rename from backend/communication-service/docs/image4.png
rename to backend/communication-service/docs/images/postman-setup4.png
diff --git a/backend/communication-service/docs/image3.png b/backend/communication-service/docs/images/postman-setup5.png
similarity index 100%
rename from backend/communication-service/docs/image3.png
rename to backend/communication-service/docs/images/postman-setup5.png
diff --git a/backend/communication-service/package-lock.json b/backend/communication-service/package-lock.json
index 20d788705e..11548b5a81 100644
--- a/backend/communication-service/package-lock.json
+++ b/backend/communication-service/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
+ "axios": "^1.7.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.1",
@@ -2492,6 +2493,23 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -2907,6 +2925,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -3091,6 +3121,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -3948,6 +3987,40 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -5869,6 +5942,12 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
diff --git a/backend/communication-service/package.json b/backend/communication-service/package.json
index c7528cb505..08fcfb3a6b 100644
--- a/backend/communication-service/package.json
+++ b/backend/communication-service/package.json
@@ -14,6 +14,7 @@
"license": "ISC",
"description": "",
"dependencies": {
+ "axios": "^1.7.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.1",
diff --git a/backend/communication-service/src/api/userService.ts b/backend/communication-service/src/api/userService.ts
new file mode 100644
index 0000000000..88442a3b6c
--- /dev/null
+++ b/backend/communication-service/src/api/userService.ts
@@ -0,0 +1,15 @@
+import axios from "axios";
+
+const USER_SERVICE_URL =
+ process.env.USER_SERVICE_URL || "http://localhost:3001/api";
+
+const userClient = axios.create({
+ baseURL: USER_SERVICE_URL,
+ withCredentials: true,
+});
+
+export const verifyToken = (token: string | undefined) => {
+ return userClient.get("/auth/verify-token", {
+ headers: { authorization: token },
+ });
+};
diff --git a/backend/communication-service/src/handlers/websocketHandler.ts b/backend/communication-service/src/handlers/websocketHandler.ts
index 92658abdf2..959c80d64e 100644
--- a/backend/communication-service/src/handlers/websocketHandler.ts
+++ b/backend/communication-service/src/handlers/websocketHandler.ts
@@ -9,6 +9,7 @@ export const handleWebsocketCommunicationEvents = (socket: Socket) => {
CommunicationEvents.JOIN,
async ({ roomId, username }: { roomId: string; username: string }) => {
connectUser(username);
+ console.log(username, roomId);
const room = io.sockets.adapter.rooms.get(roomId);
if (room?.has(socket.id)) {
socket.emit(CommunicationEvents.ALREADY_JOINED);
diff --git a/backend/communication-service/src/middlewares/basicAccessControl.ts b/backend/communication-service/src/middlewares/basicAccessControl.ts
new file mode 100644
index 0000000000..15088e9a86
--- /dev/null
+++ b/backend/communication-service/src/middlewares/basicAccessControl.ts
@@ -0,0 +1,19 @@
+import { ExtendedError, Socket } from "socket.io";
+import { verifyToken } from "../api/userService";
+
+export const verifyUserToken = (
+ socket: Socket,
+ next: (err?: ExtendedError) => void
+) => {
+ const token =
+ socket.handshake.headers.authorization || socket.handshake.auth.token;
+ verifyToken(token)
+ .then(() => {
+ console.log("Valid credentials");
+ next();
+ })
+ .catch((err) => {
+ console.error(err);
+ next(new Error("Unauthorized"));
+ });
+};
diff --git a/backend/communication-service/src/server.ts b/backend/communication-service/src/server.ts
index d3a5e530bd..5421fe6f17 100644
--- a/backend/communication-service/src/server.ts
+++ b/backend/communication-service/src/server.ts
@@ -2,16 +2,19 @@ import app, { allowedOrigins } from "./app";
import { createServer } from "http";
import { Server } from "socket.io";
import { handleWebsocketCommunicationEvents } from "./handlers/websocketHandler";
+import { verifyUserToken } from "./middlewares/basicAccessControl";
const PORT = process.env.SERVICE_PORT || 3005;
const server = createServer(app);
export const io = new Server(server, {
- cors: { origin: allowedOrigins, methods: ["GET", "POST"] },
+ cors: { origin: allowedOrigins, methods: ["GET", "POST"], credentials: true },
connectionStateRecovery: {},
});
+io.use(verifyUserToken);
+
io.on("connection", handleWebsocketCommunicationEvents);
server.listen(PORT, () => {
diff --git a/backend/matching-service/.env.sample b/backend/matching-service/.env.sample
index 83217a9e53..044f09d289 100644
--- a/backend/matching-service/.env.sample
+++ b/backend/matching-service/.env.sample
@@ -7,6 +7,7 @@ ORIGINS=http://localhost:5173,http://127.0.0.1:5173
# Other service APIs
QUESTION_SERVICE_URL=http://question-service:3000/api/questions
QN_HISTORY_SERVICE_URL=http://qn-history-service:3006/api/qnhistories
+USER_SERVICE_URL=http://user-service:3001/api
# RabbitMq configuration
RABBITMQ_DEFAULT_USER=admin
diff --git a/backend/matching-service/src/api/questionHistoryService.ts b/backend/matching-service/src/api/questionHistoryService.ts
new file mode 100644
index 0000000000..0a17c16703
--- /dev/null
+++ b/backend/matching-service/src/api/questionHistoryService.ts
@@ -0,0 +1,31 @@
+import axios from "axios";
+
+const QN_HISTORY_SERVICE_URL =
+ process.env.QN_HISTORY_SERVICE_URL ||
+ "http://qn-history-service:3006/api/qnhistories";
+
+const qnHistoryService = axios.create({
+ baseURL: QN_HISTORY_SERVICE_URL,
+ headers: {
+ "Content-Type": "application/json",
+ },
+});
+
+export const createQuestionHistory = (
+ questionId: string,
+ title: string,
+ submissionStatus: string,
+ language: string,
+ ...userIds: string[]
+) => {
+ const dateAttempted = new Date();
+ return qnHistoryService.post("/", {
+ userIds,
+ questionId,
+ title,
+ submissionStatus,
+ language,
+ dateAttempted,
+ timeTaken: 0,
+ });
+};
diff --git a/backend/matching-service/src/api/questionService.ts b/backend/matching-service/src/api/questionService.ts
new file mode 100644
index 0000000000..7599df3bc2
--- /dev/null
+++ b/backend/matching-service/src/api/questionService.ts
@@ -0,0 +1,16 @@
+import axios from "axios";
+
+const QUESTION_SERVICE_URL =
+ process.env.QUESTION_SERVICE_URL ||
+ "http://question-service:3000/api/questions";
+
+const questionClient = axios.create({
+ baseURL: QUESTION_SERVICE_URL,
+ headers: {
+ "Content-Type": "application/json",
+ },
+});
+
+export const getRandomQuestion = (complexity: string, category: string) => {
+ return questionClient.get("/random", { params: { complexity, category } });
+};
diff --git a/backend/matching-service/src/api/userService.ts b/backend/matching-service/src/api/userService.ts
new file mode 100644
index 0000000000..88442a3b6c
--- /dev/null
+++ b/backend/matching-service/src/api/userService.ts
@@ -0,0 +1,15 @@
+import axios from "axios";
+
+const USER_SERVICE_URL =
+ process.env.USER_SERVICE_URL || "http://localhost:3001/api";
+
+const userClient = axios.create({
+ baseURL: USER_SERVICE_URL,
+ withCredentials: true,
+});
+
+export const verifyToken = (token: string | undefined) => {
+ return userClient.get("/auth/verify-token", {
+ headers: { authorization: token },
+ });
+};
diff --git a/backend/matching-service/src/config/rabbitmq.ts b/backend/matching-service/src/config/rabbitmq.ts
index 966e98cbd6..0623f88b02 100644
--- a/backend/matching-service/src/config/rabbitmq.ts
+++ b/backend/matching-service/src/config/rabbitmq.ts
@@ -1,6 +1,6 @@
import amqplib, { Connection } from "amqplib";
import dotenv from "dotenv";
-import { matchUsers } from "../utils/mq_utils";
+import { matchUsers } from "../utils/messageQueue";
import { MatchRequestItem } from "../handlers/matchHandler";
import { Complexities, Categories, Languages } from "../utils/constants";
diff --git a/backend/matching-service/src/handlers/websocketHandler.ts b/backend/matching-service/src/handlers/websocketHandler.ts
index a738530bfc..74cdd526e9 100644
--- a/backend/matching-service/src/handlers/websocketHandler.ts
+++ b/backend/matching-service/src/handlers/websocketHandler.ts
@@ -11,7 +11,8 @@ import {
} from "./matchHandler";
import { io } from "../server";
import { v4 as uuidv4 } from "uuid";
-import { qnHistoryService, questionService } from "../utils/api";
+import { getRandomQuestion } from "../api/questionService";
+import { createQuestionHistory } from "../api/questionHistoryService";
enum MatchEvents {
// Receive
@@ -130,28 +131,23 @@ export const handleWebsocketMatchEvents = (socket: Socket) => {
}
const { complexity, category, language } = match;
- questionService
- .get("/random", { params: { complexity, category } })
- .then((res) => {
- const qnId = res.data.question.id;
- qnHistoryService
- .post("/", {
- userIds: [userId1, userId2],
- questionId: qnId,
- title: res.data.question.title,
- submissionStatus: "Attempted",
- dateAttempted: new Date(),
- timeTaken: 0,
- language: language,
- })
- .then((res) => {
- io.to(matchId).emit(
- MatchEvents.MATCH_SUCCESSFUL,
- qnId,
- res.data.qnHistory.id
- );
- });
+ getRandomQuestion(complexity, category).then((res) => {
+ const qnId = res.data.question.id;
+ createQuestionHistory(
+ qnId,
+ res.data.question.title,
+ "Attempted",
+ language,
+ userId1,
+ userId2
+ ).then((res) => {
+ io.to(matchId).emit(
+ MatchEvents.MATCH_SUCCESSFUL,
+ qnId,
+ res.data.qnHistory.id
+ );
});
+ });
}
}
);
diff --git a/backend/matching-service/src/middlewares/basicAccessControl.ts b/backend/matching-service/src/middlewares/basicAccessControl.ts
new file mode 100644
index 0000000000..15088e9a86
--- /dev/null
+++ b/backend/matching-service/src/middlewares/basicAccessControl.ts
@@ -0,0 +1,19 @@
+import { ExtendedError, Socket } from "socket.io";
+import { verifyToken } from "../api/userService";
+
+export const verifyUserToken = (
+ socket: Socket,
+ next: (err?: ExtendedError) => void
+) => {
+ const token =
+ socket.handshake.headers.authorization || socket.handshake.auth.token;
+ verifyToken(token)
+ .then(() => {
+ console.log("Valid credentials");
+ next();
+ })
+ .catch((err) => {
+ console.error(err);
+ next(new Error("Unauthorized"));
+ });
+};
diff --git a/backend/matching-service/src/server.ts b/backend/matching-service/src/server.ts
index fc627d78ca..0c420ce87a 100644
--- a/backend/matching-service/src/server.ts
+++ b/backend/matching-service/src/server.ts
@@ -3,8 +3,11 @@ import app, { allowedOrigins } from "./app.ts";
import { handleWebsocketMatchEvents } from "./handlers/websocketHandler.ts";
import { Server } from "socket.io";
import { connectToRabbitMq } from "./config/rabbitmq.ts";
+import { verifyToken } from "./api/userService.ts";
+import { verifyUserToken } from "./middlewares/basicAccessControl.ts";
const server = http.createServer(app);
+
export const io = new Server(server, {
cors: {
origin: allowedOrigins,
@@ -13,6 +16,8 @@ export const io = new Server(server, {
connectionStateRecovery: {},
});
+io.use(verifyUserToken);
+
io.on("connection", (socket) => {
handleWebsocketMatchEvents(socket);
});
diff --git a/backend/matching-service/src/utils/api.ts b/backend/matching-service/src/utils/api.ts
deleted file mode 100644
index 1b088f4c05..0000000000
--- a/backend/matching-service/src/utils/api.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import axios from "axios";
-
-const QUESTION_SERVICE_URL =
- process.env.QUESTION_SERVICE_URL ||
- "http://question-service:3000/api/questions";
-
-const QN_HISTORY_SERVICE_URL =
- process.env.QN_HISTORY_SERVICE_URL ||
- "http://qn-history-service:3006/api/qnhistories";
-
-export const questionService = axios.create({
- baseURL: QUESTION_SERVICE_URL,
- headers: {
- "Content-Type": "application/json",
- },
-});
-
-export const qnHistoryService = axios.create({
- baseURL: QN_HISTORY_SERVICE_URL,
- headers: {
- "Content-Type": "application/json",
- },
-});
diff --git a/backend/matching-service/src/utils/mq_utils.ts b/backend/matching-service/src/utils/messageQueue.ts
similarity index 100%
rename from backend/matching-service/src/utils/mq_utils.ts
rename to backend/matching-service/src/utils/messageQueue.ts
diff --git a/docker-compose.yml b/docker-compose.yml
index 9af939d783..1d3067ba03 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -95,6 +95,8 @@ services:
env_file: ./backend/communication-service/.env
ports:
- 3005:3005
+ depends_on:
+ - user-service
networks:
- peerprep-network
volumes:
diff --git a/frontend/src/components/Chat/index.tsx b/frontend/src/components/Chat/index.tsx
index ed2ccb0003..7bea1c2770 100644
--- a/frontend/src/components/Chat/index.tsx
+++ b/frontend/src/components/Chat/index.tsx
@@ -10,6 +10,7 @@ import {
USE_MATCH_ERROR_MESSAGE,
} from "../../utils/constants";
import { useAuth } from "../../contexts/AuthContext";
+import { toast } from "react-toastify";
type Message = {
from: string;
@@ -36,6 +37,7 @@ const Chat: React.FC = ({ isActive }) => {
const match = useMatch();
const auth = useAuth();
const messagesRef = useRef(null);
+ const errorHandledRef = useRef(false);
if (!match) {
throw new Error(USE_MATCH_ERROR_MESSAGE);
@@ -68,10 +70,17 @@ const Chat: React.FC = ({ isActive }) => {
const listener = (message: Message) => {
setMessages((prevMessages) => [...prevMessages, message]);
};
+ const errorListener = () => {
+ if (!errorHandledRef.current) {
+ toast.error("Connection error. Please try again.");
+ errorHandledRef.current = true;
+ }
+ };
communicationSocket.on(CommunicationEvents.USER_JOINED, listener);
communicationSocket.on(CommunicationEvents.TEXT_MESSAGE_RECEIVED, listener);
communicationSocket.on(CommunicationEvents.DISCONNECTED, listener);
+ communicationSocket.on(CommunicationEvents.CONNECT_ERROR, errorListener);
return () => {
communicationSocket.off(CommunicationEvents.USER_JOINED, listener);
@@ -80,6 +89,7 @@ const Chat: React.FC = ({ isActive }) => {
listener
);
communicationSocket.off(CommunicationEvents.DISCONNECTED, listener);
+ communicationSocket.off(CommunicationEvents.CONNECT_ERROR, errorListener);
};
}, []);
diff --git a/frontend/src/utils/collabSocket.ts b/frontend/src/utils/collabSocket.ts
index 4fe50bafe3..1d252552cc 100644
--- a/frontend/src/utils/collabSocket.ts
+++ b/frontend/src/utils/collabSocket.ts
@@ -33,9 +33,13 @@ export type CollabSessionData = {
};
const COLLAB_SOCKET_URL = "http://localhost:3003";
+
export const collabSocket = io(COLLAB_SOCKET_URL, {
reconnectionAttempts: 3,
autoConnect: false,
+ auth: {
+ token: `Bearer ${localStorage.getItem("token")}`,
+ },
});
let doc: Doc;
diff --git a/frontend/src/utils/communicationSocket.ts b/frontend/src/utils/communicationSocket.ts
index 51cc908a10..cff0006ddb 100644
--- a/frontend/src/utils/communicationSocket.ts
+++ b/frontend/src/utils/communicationSocket.ts
@@ -11,6 +11,7 @@ export enum CommunicationEvents {
USER_JOINED = "user_joined",
ALREADY_JOINED = "already_joined",
TEXT_MESSAGE_RECEIVED = "text_message_received",
+ CONNECT_ERROR = "connect_error",
DISCONNECTED = "disconnected",
}
@@ -19,4 +20,8 @@ const COMMUNICATION_SOCKET_URL = "http://localhost:3005";
export const communicationSocket = io(COMMUNICATION_SOCKET_URL, {
reconnectionAttempts: 3,
autoConnect: false,
+ withCredentials: true,
+ auth: {
+ token: `Bearer ${localStorage.getItem("token")}`,
+ },
});
diff --git a/frontend/src/utils/matchSocket.ts b/frontend/src/utils/matchSocket.ts
index e79801a6b4..4ef4d2038b 100644
--- a/frontend/src/utils/matchSocket.ts
+++ b/frontend/src/utils/matchSocket.ts
@@ -5,4 +5,7 @@ const MATCH_SOCKET_URL = "http://localhost:3002";
export const matchSocket = io(MATCH_SOCKET_URL, {
reconnectionAttempts: 3,
autoConnect: false,
+ auth: {
+ token: `Bearer ${localStorage.getItem("token")}`,
+ },
});