mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
added jwt token to room routes
This commit is contained in:
parent
35d6724d87
commit
977d1c9700
9 changed files with 88 additions and 162 deletions
|
|
@ -81,7 +81,7 @@ const ManageRoom: React.FC = () => {
|
||||||
|
|
||||||
const createWebSocketRoom = async () => {
|
const createWebSocketRoom = async () => {
|
||||||
setConnectingError('');
|
setConnectingError('');
|
||||||
const room = await (await fetch('/api/room', { method: 'post' })).json();
|
const room = await ApiService.createRoom();
|
||||||
const socket = webSocketService.connect(`/api/room/${room.id}/socket`);
|
const socket = webSocketService.connect(`/api/room/${room.id}/socket`);
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,78 @@ class ApiService {
|
||||||
return localStorage.removeItem("jwt");
|
return localStorage.removeItem("jwt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Socket Route
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new room.
|
||||||
|
* @returns The room object if successful
|
||||||
|
* @returns An error string if unsuccessful
|
||||||
|
*/
|
||||||
|
public async createRoom(): Promise<any> {
|
||||||
|
try {
|
||||||
|
const url: string = this.constructRequestUrl(`/room`);
|
||||||
|
const headers = this.constructRequestHeaders();
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`La création de la salle a échoué. Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const room = await response.json();
|
||||||
|
return room;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error details: ", error);
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return error.message || 'Erreur serveur inconnue lors de la requête.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return `Une erreur inattendue s'est produite.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a room by its name.
|
||||||
|
* @param roomName - The name of the room to delete.
|
||||||
|
* @returns true if successful
|
||||||
|
* @returns An error string if unsuccessful
|
||||||
|
*/
|
||||||
|
public async deleteRoom(roomName: string): Promise<any> {
|
||||||
|
try {
|
||||||
|
if (!roomName) {
|
||||||
|
throw new Error(`Le nom de la salle est requis.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = this.constructRequestUrl(`/room/${roomName}`);
|
||||||
|
const headers = this.constructRequestHeaders();
|
||||||
|
fetch(url, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error details: ", error);
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return error.message || 'Erreur serveur inconnue lors de la requête.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return `Une erreur inattendue s'est produite.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// User Routes
|
// User Routes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -302,6 +374,7 @@ class ApiService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns folder array if successful
|
* @returns folder array if successful
|
||||||
* @returns A error string if unsuccessful,
|
* @returns A error string if unsuccessful,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// WebSocketService.tsx
|
// WebSocketService.tsx
|
||||||
import { io, Socket } from 'socket.io-client';
|
import { io, Socket } from 'socket.io-client';
|
||||||
|
import apiService from './ApiService';
|
||||||
|
|
||||||
// Must (manually) sync these types to server/socket/socket.js
|
// Must (manually) sync these types to server/socket/socket.js
|
||||||
|
|
||||||
|
|
@ -63,7 +64,7 @@ class WebSocketService {
|
||||||
if (this.socket) {
|
if (this.socket) {
|
||||||
this.socket.emit('end-quiz', { roomName });
|
this.socket.emit('end-quiz', { roomName });
|
||||||
//Delete room in mongoDb, roomContainer will be deleted in cleanup
|
//Delete room in mongoDb, roomContainer will be deleted in cleanup
|
||||||
fetch(`/api/room/${roomName}`, { method: 'DELETE' });
|
apiService.deleteRoom(roomName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ async function fetchRoomInfo(r) {
|
||||||
let res = await r.subrequest('/api/room/' + r.variables.room_id, {
|
let res = await r.subrequest('/api/room/' + r.variables.room_id, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
r.error(`Failed to fetch room info: ${res.status}`);
|
r.error(`Failed to fetch room info: ${res.status}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let room = JSON.parse(res.responseText);
|
let room = JSON.parse(res.responseText);
|
||||||
r.error(`Debug: Room info: ${JSON.stringify(room)}`); // Debug log
|
r.error(`Debug: Room info: ${JSON.stringify(room)}`); // Debug log
|
||||||
return room;
|
return room;
|
||||||
|
|
@ -22,7 +22,7 @@ async function fetchRoomInfo(r) {
|
||||||
async function routeWebSocket(r) {
|
async function routeWebSocket(r) {
|
||||||
try {
|
try {
|
||||||
const roomInfo = await fetchRoomInfo(r);
|
const roomInfo = await fetchRoomInfo(r);
|
||||||
|
|
||||||
if (!roomInfo || !roomInfo.host) {
|
if (!roomInfo || !roomInfo.host) {
|
||||||
r.error(`Debug: Invalid room info: ${JSON.stringify(roomInfo)}`);
|
r.error(`Debug: Invalid room info: ${JSON.stringify(roomInfo)}`);
|
||||||
r.return(404, 'Room not found or invalid');
|
r.return(404, 'Room not found or invalid');
|
||||||
|
|
@ -38,13 +38,13 @@ async function routeWebSocket(r) {
|
||||||
r.error(`Debug: Original URL: ${r.uri}`);
|
r.error(`Debug: Original URL: ${r.uri}`);
|
||||||
r.error(`Debug: Setting proxy target to: ${proxyUrl}`);
|
r.error(`Debug: Setting proxy target to: ${proxyUrl}`);
|
||||||
r.error(`Debug: Headers: ${JSON.stringify(r.headersIn)}`);
|
r.error(`Debug: Headers: ${JSON.stringify(r.headersIn)}`);
|
||||||
|
|
||||||
// Set the proxy target variable
|
// Set the proxy target variable
|
||||||
r.variables.proxy_target = proxyUrl;
|
r.variables.proxy_target = proxyUrl;
|
||||||
|
|
||||||
// Redirect to the websocket proxy
|
// Redirect to the websocket proxy
|
||||||
r.internalRedirect('@websocket_proxy');
|
r.internalRedirect('@websocket_proxy');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
r.error(`WebSocket routing error: ${error}`);
|
r.error(`WebSocket routing error: ${error}`);
|
||||||
r.return(500, 'Internal routing error');
|
r.return(500, 'Internal routing error');
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,6 @@ const express = require("express");
|
||||||
const http = require("http");
|
const http = require("http");
|
||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
|
|
||||||
// Import Sockets
|
|
||||||
const { setupWebsocket } = require("./socket/socket");
|
|
||||||
const { Server } = require("socket.io");
|
|
||||||
|
|
||||||
// instantiate the db
|
// instantiate the db
|
||||||
const db = require('./config/db.js');
|
const db = require('./config/db.js');
|
||||||
// instantiate the models
|
// instantiate the models
|
||||||
|
|
@ -61,28 +57,10 @@ const app = express();
|
||||||
const cors = require("cors");
|
const cors = require("cors");
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
|
|
||||||
|
|
||||||
const configureServer = (httpServer, isDev) => {
|
|
||||||
return new Server(httpServer, {
|
|
||||||
path: "/socket.io",
|
|
||||||
cors: {
|
|
||||||
origin: "*",
|
|
||||||
methods: ["GET", "POST"],
|
|
||||||
credentials: true,
|
|
||||||
},
|
|
||||||
secure: !isDev, // true for https, false for http
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start sockets (depending on the dev or prod environment)
|
|
||||||
let server = http.createServer(app);
|
let server = http.createServer(app);
|
||||||
let isDev = process.env.NODE_ENV === 'development';
|
let isDev = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
console.log(`Environnement: ${process.env.NODE_ENV} (${isDev ? 'dev' : 'prod'})`);
|
console.log(`Environnement: ${process.env.NODE_ENV} (${isDev ? 'dev' : 'prod'})`);
|
||||||
|
|
||||||
const io = configureServer(server);
|
|
||||||
|
|
||||||
setupWebsocket(io);
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class Token {
|
||||||
if (error) {
|
if (error) {
|
||||||
throw new AppError(UNAUTHORIZED_INVALID_TOKEN)
|
throw new AppError(UNAUTHORIZED_INVALID_TOKEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.user = payload;
|
req.user = payload;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
const Docker = require("dockerode");
|
const Docker = require("dockerode");
|
||||||
const { Room, RoomRepository } = require("../models/room.js");
|
const { Room } = require("../models/room.js");
|
||||||
const BaseRoomProvider = require("./base-provider.js");
|
const BaseRoomProvider = require("./base-provider.js");
|
||||||
|
|
||||||
class DockerRoomProvider extends BaseRoomProvider {
|
class DockerRoomProvider extends BaseRoomProvider {
|
||||||
|
|
@ -126,7 +126,6 @@ class DockerRoomProvider extends BaseRoomProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async deleteRoom(roomId) {
|
async deleteRoom(roomId) {
|
||||||
const container_name = `room_${roomId}`;
|
const container_name = `room_${roomId}`;
|
||||||
await this.roomRepository.delete(roomId);
|
await this.roomRepository.delete(roomId);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const jwt = require('../middleware/jwtToken.js');
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get("/", async (req, res)=> {
|
router.get("/",jwt.authenticate, async (req, res)=> {
|
||||||
try {
|
try {
|
||||||
const data = await roomsController.listRooms();
|
const data = await roomsController.listRooms();
|
||||||
res.json(data);
|
res.json(data);
|
||||||
|
|
@ -14,7 +14,7 @@ router.get("/", async (req, res)=> {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
router.post("/", async (req, res) => {
|
router.post("/",jwt.authenticate, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const data = await roomsController.createRoom();
|
const data = await roomsController.createRoom();
|
||||||
res.json(data);
|
res.json(data);
|
||||||
|
|
@ -24,7 +24,7 @@ router.post("/", async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put("/:id", async (req, res) => {
|
router.put("/:id",jwt.authenticate, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const data = await roomsController.updateRoom(req.params.id);
|
const data = await roomsController.updateRoom(req.params.id);
|
||||||
res.json(data);
|
res.json(data);
|
||||||
|
|
@ -33,7 +33,7 @@ router.put("/:id", async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.delete("/:id", async (req, res) => {
|
router.delete("/:id",jwt.authenticate, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const data = await roomsController.deleteRoom(req.params.id);
|
const data = await roomsController.deleteRoom(req.params.id);
|
||||||
res.json(data);
|
res.json(data);
|
||||||
|
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
const MAX_USERS_PER_ROOM = 60;
|
|
||||||
const MAX_TOTAL_CONNECTIONS = 2000;
|
|
||||||
|
|
||||||
const setupWebsocket = (io) => {
|
|
||||||
let totalConnections = 0;
|
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
|
||||||
if (totalConnections >= MAX_TOTAL_CONNECTIONS) {
|
|
||||||
console.log("Connection limit reached. Disconnecting client.");
|
|
||||||
socket.emit(
|
|
||||||
"join-failure",
|
|
||||||
"Le nombre maximum de connexions a été atteint"
|
|
||||||
);
|
|
||||||
socket.disconnect(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalConnections++;
|
|
||||||
// console.log(
|
|
||||||
// "A user connected:",
|
|
||||||
// socket.id,
|
|
||||||
// "| Total connections:",
|
|
||||||
// totalConnections
|
|
||||||
// );
|
|
||||||
|
|
||||||
socket.on("create-room", (sentRoomName) => {
|
|
||||||
if (sentRoomName) {
|
|
||||||
const roomName = sentRoomName.toUpperCase();
|
|
||||||
if (!io.sockets.adapter.rooms.get(roomName)) {
|
|
||||||
socket.join(roomName);
|
|
||||||
socket.emit("create-success", roomName);
|
|
||||||
} else {
|
|
||||||
socket.emit("create-failure");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const roomName = generateRoomName();
|
|
||||||
if (!io.sockets.adapter.rooms.get(roomName)) {
|
|
||||||
socket.join(roomName);
|
|
||||||
socket.emit("create-success", roomName);
|
|
||||||
} else {
|
|
||||||
socket.emit("create-failure");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("join-room", ({ enteredRoomName, username }) => {
|
|
||||||
if (io.sockets.adapter.rooms.has(enteredRoomName)) {
|
|
||||||
const clientsInRoom =
|
|
||||||
io.sockets.adapter.rooms.get(enteredRoomName).size;
|
|
||||||
|
|
||||||
if (clientsInRoom <= MAX_USERS_PER_ROOM) {
|
|
||||||
const newStudent = {
|
|
||||||
id: socket.id,
|
|
||||||
name: username,
|
|
||||||
answers: [],
|
|
||||||
};
|
|
||||||
socket.join(enteredRoomName);
|
|
||||||
socket
|
|
||||||
.to(enteredRoomName)
|
|
||||||
.emit("user-joined", newStudent);
|
|
||||||
socket.emit("join-success");
|
|
||||||
} else {
|
|
||||||
socket.emit("join-failure", "La salle est remplie");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
socket.emit("join-failure", "Le nom de la salle n'existe pas");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("next-question", ({ roomName, question }) => {
|
|
||||||
// console.log("next-question", roomName, question);
|
|
||||||
socket.to(roomName).emit("next-question", question);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("launch-student-mode", ({ roomName, questions }) => {
|
|
||||||
socket.to(roomName).emit("launch-student-mode", questions);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("end-quiz", ({ roomName }) => {
|
|
||||||
socket.to(roomName).emit("end-quiz");
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("message", (data) => {
|
|
||||||
console.log("Received message from", socket.id, ":", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("disconnect", () => {
|
|
||||||
totalConnections--;
|
|
||||||
console.log(
|
|
||||||
"A user disconnected:",
|
|
||||||
socket.id,
|
|
||||||
"| Total connections:",
|
|
||||||
totalConnections
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const [room] of io.sockets.adapter.rooms) {
|
|
||||||
if (room !== socket.id) {
|
|
||||||
io.to(room).emit("user-disconnected", socket.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("submit-answer", ({ roomName, username, answer, idQuestion }) => {
|
|
||||||
socket.to(roomName).emit("submit-answer-room", {
|
|
||||||
idUser: socket.id,
|
|
||||||
username,
|
|
||||||
answer,
|
|
||||||
idQuestion,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const generateRoomName = (length = 6) => {
|
|
||||||
const characters = "0123456789";
|
|
||||||
let result = "";
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
result += characters.charAt(
|
|
||||||
Math.floor(Math.random() * characters.length)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = { setupWebsocket };
|
|
||||||
Loading…
Reference in a new issue