From d9bf196c2faf020dac08fb46677afbc12a297dbb Mon Sep 17 00:00:00 2001
From: "narindra.rajohnso" <narindra-hasimanjaka-david.rajohnson@etu.hesge.ch>
Date: Fri, 9 Jun 2023 02:35:36 +0200
Subject: [PATCH] add socket io logic

---
 API/src/database/database.sqlite | Bin 20480 -> 20480 bytes
 API/src/express/Server.ts        |  44 +++++++++++++++------
 API/src/routes/middleware.ts     |   4 +-
 API/src/routes/router-guest.ts   |   2 +-
 API/src/socket.io/ServerIO.ts    |  64 ++++++++++++++++++++++++++++---
 API/src/socket.io/UserInfo.ts    |   7 ++++
 6 files changed, 102 insertions(+), 19 deletions(-)

diff --git a/API/src/database/database.sqlite b/API/src/database/database.sqlite
index ed7be32ccd95fadcfdba4d8983a6d5731c58f8a2..3b0f607132d41b2d59a2ed5c6fefffe988f5b37b 100644
GIT binary patch
delta 586
zcmZozz}T>Wae_2s@kAMC#^Q|$3;AVvwli>Xl{4@w@wM~!@xJ8^;gROq&E3Pz$W_jH
zVPoS~&dHZ0mk2hp^Kgo%it@{fdU}?m7MB=LHk8qc1GB({LwZ_iacYr~fswJUftjv>
zg@Tc>m65rXv9X?ofr)~)fq|8Q0e;y=4sNg&@=z-bK~}_rOg97*4(Y`yn06Q%TA7;Z
z8CY6iwF6zYk%x;@JXKs+5o(7K$PVwa{LGxh-26-!ZEAsLkD;NJp^24|g`TN_8KynR
zvXez*7E3WOFt9X=adIlAii&EBdU}FPE67Q#G&h-CC8ZM(TAW%Gkds&m6Lu&mF49ZR
z0CAB*2xO|Um5G6#k%cjKJ7Kb$ePy>Y$*f}F;;&%fzs&!Re+T~^{@MIZ{OkBD_>b}T
z@Xy~Y=n%~B&i{jfr?9+=lUbY*6rjdDFqR=VAG0DO$bN_`IYHdwlGL)S#KO|l5)S?!
Q3@k9UMqHbB=zAyt0HD~J-2eap

delta 721
zcmZozz}T>Wae_2s-b5K^#=MOQ3;AUk7#P@jq#5{?_}cmVc;E7d@NDOi=I-bE!j;B(
zVPoS~&dHZ0moTTKSxmktqf?)jSe%lUSe%xUQk<4p>`<JNrk9*jTAW&BWME{hYhbEt
zWU63bX=P$&Wn`#lX<)9PZD3$!V1Qkgfq{Wxigc=|sJf`9XK`A2TDgU(Sw={1kXuD=
zenh&zPe_Jmut#}`m#2S4cxiH$XJCCuYQBYkeo0xLK}vF{Eyy7t40e@68pt&{=&ms|
zurjc;GPKmQFg3z-jiIrXp{13HrJjkQAygLRs!7tR3=9lC!l|O7@*uaRq<LxkJGmOw
zm#6!NhE#=Gx_US|C2O1c=4vO0r22$9r6uVbnU*+Ons}C{d)h(*DJ88qF(u6bL?A-Q
zOxM6%!O+CY)Y!_@LeI>?1ZpcJgmB3=N^)>2rb<dqR+gDk-zde-DW57TtuN~7S&~{@
z;+J1qX6_T^5#i_^7*H4z6%pxao*$g;nHA_^Zeiw=?wyrw9$f01993dg5mb?!Y#RdA
zl$uxy(w~=KT9%qv>QIuZS5ky<sj04!fr6otm7$rHv5}sM87%a~Ax_1R-s~&8l}Y9Y
z13Uk02L8+Z@A!A{-{GIlzl#4D|1tjgAh=o3A(-Et{|5t4VR=<?hJ`8r4+h@CloU|J
yS%8F#)5<|qS$<|tqM->VAG0E3aY<@fR$^gkY6%A~vpgfny<q>cZ{DHrp#T8WtIlTt

diff --git a/API/src/express/Server.ts b/API/src/express/Server.ts
index b9adf9b..e45eed1 100644
--- a/API/src/express/Server.ts
+++ b/API/src/express/Server.ts
@@ -1,25 +1,35 @@
-import { Express }      from 'express-serve-static-core';
-import cors             from 'cors';
+import {Express} from 'express-serve-static-core';
+import cors from 'cors';
 import morganMiddleware from '../logging/MorganMiddleware';
-import logger           from '../logging/WinstonLogger';
-import { AddressInfo }  from 'net';
-import http             from 'http';
-import helmet           from 'helmet';
-import express          from 'express';
-import multer           from 'multer';
-import Config           from '../config/Config';
-import BaseRoutes       from '../routes/BaseRoutes';
-import ServerIO         from '../socket.io/ServerIO';
-import routerUser from "../routes/router-gamer";
+import logger from '../logging/WinstonLogger';
+import {AddressInfo} from 'net';
+import http from 'http';
+import helmet from 'helmet';
+import express from 'express';
+import multer from 'multer';
+import Config from '../config/Config';
+import BaseRoutes from '../routes/BaseRoutes';
+import ServerIO from '../socket.io/ServerIO';
 import routerGamer from "../routes/router-gamer";
 import routerGuest from "../routes/router-guest";
 import routerAdmin from "../routes/router-admin";
+import jwt from 'jsonwebtoken';
+import * as IO from 'socket.io';
+
+
+export interface SocketIoInfo extends IO.Socket{
+    user :any;
+}
+
+
 
 
 class Server {
     private readonly backend: Express;
     private readonly server: http.Server;
     private readonly io: ServerIO;
+    public static invalidTokens: string[] = [];
+
 
     constructor() {
         this.backend = express();
@@ -52,6 +62,16 @@ class Server {
         this.server = http.createServer(this.backend);
 
         this.io = new ServerIO(this.server);
+        this.io.use((socket: SocketIoInfo, next) => {
+            const token = socket.handshake.auth.token;
+
+            try {
+                socket.user = jwt.verify(token, process.env.SECRET_KEY);
+                next();
+            } catch (error) {
+                next(new Error('Invalid token'));
+            }
+        });
     }
 
     run() {
diff --git a/API/src/routes/middleware.ts b/API/src/routes/middleware.ts
index 3c3164c..56be529 100644
--- a/API/src/routes/middleware.ts
+++ b/API/src/routes/middleware.ts
@@ -47,6 +47,8 @@ export interface TokenRequest extends express.Request {
     user?: any;
 }
 
+
+
 export async function verifyToken(req: TokenRequest, res: express.Response, next: express.NextFunction) {
     const authHeader = req.headers['authorization'];
 
@@ -59,7 +61,7 @@ export async function verifyToken(req: TokenRequest, res: express.Response, next
 
     try {
         req.user = jwt.verify(token, secretKey);
-        if(req.user.username !== req.params.admin)
+        if(req.user.username !== req.params.admin && req.user.username !== req.params.username)
             return res.status(403).json({message: 'Invalid token user'});
         //check if admin or user
         next();
diff --git a/API/src/routes/router-guest.ts b/API/src/routes/router-guest.ts
index ad6875e..3272887 100644
--- a/API/src/routes/router-guest.ts
+++ b/API/src/routes/router-guest.ts
@@ -29,7 +29,7 @@ router.post('/:username', checkExistingUser, async (req: express.Request, res: e
         let usertype=user.dataValues.type === "user"?"USER":"ADMIN"
         if (user.dataValues.password === data.password) {
             // Génération du token JWT
-            const userInfo={ type: userType, username: req.params.username, firstname: user.dataValues.firstname, lastname: user.dataValues.lastname }
+            const userInfo={ type: user.dataValues.type, username: req.params.username, firstname: user.dataValues.firstname, lastname: user.dataValues.lastname }
             const secretKey=process.env.SECRET_KEY;
             const token = jwt.sign(userInfo, secretKey);
             res.status(StatusCodes.OK).json({message: usertype+"_ALLOWED", token: token, firstname: user.dataValues.firstname, lastname: user.dataValues.lastname});
diff --git a/API/src/socket.io/ServerIO.ts b/API/src/socket.io/ServerIO.ts
index 11e53d4..9ec2874 100644
--- a/API/src/socket.io/ServerIO.ts
+++ b/API/src/socket.io/ServerIO.ts
@@ -1,11 +1,16 @@
 import * as IO from 'socket.io';
 import logger  from '../logging/WinstonLogger';
 import http    from 'http';
+import Server, {SocketIoInfo} from "../express/Server";
+import {UserInfo} from "./UserInfo"
 
 
 //TODO: In this file you can add/edit all things about socket.io
 
+
+
 class ServerIO extends IO.Server {
+    players: { [key: string]: UserInfo } = {};
     constructor(server: http.Server) {
         super(server, {
             cors: {
@@ -13,18 +18,67 @@ class ServerIO extends IO.Server {
             }
         });
 
-        this.on('connection', (socket: IO.Socket) => {
-            logger.info(`Nouveau socket vers ${ socket.client.conn.remoteAddress }`);
+
+        this.on('connection', (socket: SocketIoInfo) => {
+            logger.info(`Nouveau socket vers ${ socket.client.conn.remoteAddress }`) ;
+            console.log(`Socket info: ${ socket.user.username } // ${ socket.user.firstname } // ${socket.user.lastname}`);
+            const playerKey = socket.user.username;
+            // Vérifiez si le joueur existe déjà dans le dictionnaire
+            if (this.players[playerKey]) {
+                // Le joueur est déjà connecté, vous pouvez effectuer une action appropriée ici
+                console.log(`Player ${playerKey} is already connected.`);
+            } else {
+                // Le joueur n'est pas encore connecté, ajoutez-le au dictionnaire
+                this.players[playerKey] = new UserInfo(
+                    socket.user.username,
+                    socket.user.firstname,
+                    socket.user.lastname
+                );
+                console.log(`Player ${playerKey} is connected.`);
+            }
+
+            this.testNumberofPlayer();
+
 
             this.registerEventsOnSocket(socket);
         });
+
+
     }
 
-    private registerEventsOnSocket(socket: IO.Socket) {
-        socket.on('Hello World', _ => {
-            socket.emit('Bienvenue', socket.id);
+    private registerEventsOnSocket(socket: SocketIoInfo) {
+
+        socket.on('disconnect', () => {
+            logger.info(`Deconnexion du socket ${ socket.client.conn.remoteAddress }`) ;
+            console.log(`Socket info: ${ socket.user.username } // ${ socket.user.firstname } // ${socket.user.lastname}`);
+            const playerKey = socket.user.username;
+
+
+            // Vérifiez si le joueur est dans le dictionnaire
+            if (this.players[playerKey]) {
+                // Le joueur est connecté, retirez-le du dictionnaire
+                delete this.players[playerKey];
+                console.log(`Player ${playerKey} is disconnected.`);
+            } else {
+                // Le joueur n'est pas trouvé dans le dictionnaire, cela peut être un cas anormal
+                console.log(`Player ${playerKey} is not connected.`);
+            }
+            this.testNumberofPlayer();
+
         });
     }
+
+    private testNumberofPlayer(){
+        if(Object.keys(this.players).length < 3){
+            this.emit("players-left", 3 - Object.keys(this.players).length)
+            console.log(Object.keys(this.players).length)
+        }
+
+        if (Object.keys(this.players).length === 3) {
+            // Démarre le jeu
+            this.emit('start-game');
+        }
+    }
 }
 
 
diff --git a/API/src/socket.io/UserInfo.ts b/API/src/socket.io/UserInfo.ts
index e69de29..079aa86 100644
--- a/API/src/socket.io/UserInfo.ts
+++ b/API/src/socket.io/UserInfo.ts
@@ -0,0 +1,7 @@
+export class UserInfo {
+    constructor(
+        public username: string,
+        public firstname: string,
+        public lastname: string
+    ){}
+}
\ No newline at end of file
-- 
GitLab