diff --git a/.gitignore b/.gitignore index 140fa633..1cc82b66 100644 --- a/.gitignore +++ b/.gitignore @@ -15,13 +15,11 @@ Thumbs.db *.log # compiled output -/dist node_modules -./srcs/requirement/api_back/node_modules -./srcs/requirement/api_back/dist -./srcs/requirement/api_front/node_modules -./srcs/requirement/api_front/public/build +./srcs/requirement/nestjs/api_back/dist +./srcs/requirements/svelte/api_front/public/build/ + # Logs logs *.log @@ -53,3 +51,7 @@ lerna-debug.log* !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json + +.env + +memo.txt diff --git a/README.md b/README.md index fa49b455..1e5589a2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js +- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js.map + ### Pour lancer le docker : diff --git a/make_env.sh b/make_env.sh old mode 100644 new mode 100755 index e097ccd7..7c218de4 --- a/make_env.sh +++ b/make_env.sh @@ -1,6 +1,12 @@ #! /usr/bin/env bash - +ENV_FILE_DOCKER=./srcs/.env +ENV_FILE_SVELTE=./srcs/requirements/svelte/api_front/.env +NGINX_CONF_FILE=./srcs/requirements/nginx/conf/default.conf +BOLD_RED="\033[1;31m" +BOLD_GREEN="\033[1;32m" +BOLD_BLUE="\033[1;34m" +RESET="\033[0m" # Function to generate passwords # @@ -12,87 +18,131 @@ echo $(openssl rand -base64 32 | tr "/" "_" ); } + function make_env_for_svelte + { + echo -e "${BOLD_BLUE}Creating a new environment for svelte${RESET}" + grep "^WEBSITE_" "$ENV_FILE_DOCKER" > "$ENV_FILE_SVELTE" + } + function update_nginx_conf + { + echo -e "${BOLD_BLUE}Updating the nginx conf${RESET}" + echo -e "${BOLD_RED}WARNING : If for some reason you've changed the port, you MUST change it inside the nginx conf file. It's not supposed to change.${RESET}" + HOST=$(grep "^WEBSITE_HOST" $ENV_FILE_DOCKER | cut -d "=" -f 2) + sed -i "s/server_name.*/server_name $HOST;/g" "$NGINX_CONF_FILE" + } -# This script is used to create a new environment for the project. -# - ENV_FILE_DOCKER=./srcs/.env - ENV_FILE_NESTJS=./srcs/requirements/nestjs/api_back/.env - # Check for existing .env - if [ -f "$ENV_FILE_DOCKER" ] && [ -f "$ENV_FILE_NESTJS" ]; then - echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS already exists. Do you want to overwrite them ? (y/n)" - OVERWRITE="" - # Ask to overwrite the .env files - while [ "$OVERWRITE" != "y" ] && [ "$OVERWRITE" != "n" ]; do - read -p "Enter your choice : " OVERWRITE + function make_env_for_docker_and_svelte + { + docker rm -f postgresql + docker volume rm -f srcs_data_nest_postgresql + echo -e "${BOLD_BLUE}Creating a new environment for docker${RESET}" + NODE_ENV="" + # Ask if dev or prod environment + while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do + read -p "Enter the env configuration for nestjs : \"1\" for development OR \"2\" for production : " NODE_ENV done - if [ "$OVERWRITE" = "y" ]; then - rm "$ENV_FILE_DOCKER" && rm "$ENV_FILE_NESTJS" - docker rmi -f postgres + if [ "$NODE_ENV" = "1" ]; then + echo "NODE_ENV=development" > "$ENV_FILE_DOCKER" else - echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS will not be overwritten. The script will exit." + echo "NODE_ENV=production" > "$ENV_FILE_DOCKER" + fi + read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST + echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER" + echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER" + echo "POSTGRES_USER=postgres" >> "$ENV_FILE_DOCKER" + echo "#if change postgres pswd, do make destroy" >> "$ENV_FILE_DOCKER" + echo "POSTGRES_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER" + echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_DOCKER" + echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_DOCKER" + echo "POSTGRES_PORT=5432" >> "$ENV_FILE_DOCKER" + echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER" + echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER" + echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER" + # Connection to 42 + echo -e "${BOLD_BLUE}In the next steps, we'll need to enter the client secret and client id of the 42 api${RESET}" + read -p "Enter the client id of the 42 api : " CLIENT_ID + echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_DOCKER" + read -p "Enter the client secret of the 42 api : " CLIENT_SECRET + echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_DOCKER" + FT_CALLBACK="http://$PROJECT_HOST:8080/api/v2/auth/redirect" + echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_DOCKER" + # Other configs + echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_DOCKER" + echo "PORT=3000" >> "$ENV_FILE_DOCKER" + echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_DOCKER" + echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_DOCKER" + make_env_for_svelte + update_nginx_conf + echo -e "${BOLD_GREEN}Environment created.${RESET}" + echo -e "${BOLD_GREEN}The script will exit${RESET}" + exit 0 + } + + function change_host_and_port_api + { + if [ -f "$ENV_FILE_DOCKER" ] + then + echo -e "${BOLD_BLUE}Changing the host and the port of the api${RESET}" + read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST + sed -i "s/WEBSITE_HOST=.*/WEBSITE_HOST=$PROJECT_HOST/g" "$ENV_FILE_DOCKER" + read -p "Enter the port of the api : " PROJECT_PORT + sed -i "s/WEBSITE_PORT=.*/WEBSITE_PORT=$PROJECT_PORT/g" "$ENV_FILE_DOCKER" + make_env_for_svelte + update_nginx_conf + else + echo -e "${BOLD_RED}No environment file found. We will regenerate the entire env files.${RESET}" + fi + } + + function change_api_fields_for_42_auth_api + { + if [ -f "$ENV_FILE_DOCKER" ] + then + echo -e "${BOLD_BLUE}Changing the secret for the 42 api${RESET}" + read -p "Enter the client id of the 42 api : " CLIENT_ID + sed -i "s/FORTYTWO_CLIENT_ID=.*/FORTYTWO_CLIENT_ID=$CLIENT_ID/g" "$ENV_FILE_DOCKER" + read -p "Enter the client secret of the 42 api : " CLIENT_SECRET + sed -i "s/FORTYTWO_CLIENT_SECRET=.*/FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET/g" "$ENV_FILE_DOCKER" + echo -e "${BOLD_GREEN}The fields concerning the 42 api have been changed.${RESET}" + else + echo -e "${BOLD_RED}No environment file found. We will regenerate the entire env files.${RESET}" + make_env_for_docker_and_svelte + fi + } + + + function choose_options_and_process { + if [ ! -f "$ENV_FILE_DOCKER" ]; then + make_env_for_docker_and_svelte + elif [ ! -f "$ENV_FILE_SVELTE" && -f "$ENV_FILE_DOCKER" ]; then + make_env_for_svelte + fi + echo -e "${BOLD_RED}An environment already exists.${RESET}" + echo -e "${BOLD_GREEN}What do you want to do ?${RESET}" + echo -e "${BOLD_GREEN}1. Regenerate entire environment${RESET}" + echo -e "${BOLD_GREEN}2. Only change the fields about the HOSTNAME and the PORT of the API${RESET}" + echo -e "${BOLD_GREEN}3. Only change the fields concerning the 42 API (id and secret)${RESET}" + echo -e "${BOLD_GREEN}4. Exit${RESET}" + CHOICE="" + while [ "$CHOICE" != "1" ] && [ "$CHOICE" != "2" ] && [ "$CHOICE" != "3" ] && [ "$CHOICE" != "4" ]; do + read -p "Enter your choice : " CHOICE + done + if [ "$CHOICE" = "1" ]; then + make_env_for_docker_and_svelte + elif [ "$CHOICE" = "2" ]; then + change_host_and_port_api + elif [ "$CHOICE" = "3" ]; then + change_api_fields_for_42_auth_api + else + echo -e "${BOLD_GREEN}The script will exit.${RESET}" exit 0 fi - fi + } +# Create a new environment for docker + choose_options_and_process -# Create a new environment for docker -# - echo "Creating a new environment for docker" - NODE_ENV="" - # Ask if dev or prod environment - while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do - read -p "Enter the env configuration for nestjs : \"1\" for development OR \"2\" for production : " NODE_ENV - done - if [ "$NODE_ENV" = "1" ]; then - echo "NODE_ENV=development" > "$ENV_FILE_DOCKER" - else - echo "NODE_ENV=production" > "$ENV_FILE_DOCKER" - fi - # Env variables - read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST - echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER" - echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER" - echo "POSTGRES_USER=postgres" >> "$ENV_FILE_DOCKER" - echo "#if change postgres pswd, do make destroy" >> "$ENV_FILE_DOCKER" - echo "POSTGRES_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER" - echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_DOCKER" - echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_DOCKER" - echo "POSTGRES_PORT=5432" >> "$ENV_FILE_DOCKER" - echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER" - echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER" - echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER" - - - -# Create a new environment for nestjs -# - echo "Creating a new environment for nestjs" - echo "NODE_ENV=\$NODE_ENV" > "$ENV_FILE_NESTJS" - echo "WEBSITE_HOST=\$WEBSITE_HOST" >> "$ENV_FILE_NESTJS" - echo "WEBSITE_PORT=\$WEBSITE_PORT" >> "$ENV_FILE_NESTJS" - echo "POSTGRES_USER=\$POSTGRES_USER" >> "$ENV_FILE_NESTJS" - echo "POSTGRES_PASSWORD=\$POSTGRES_PASSWORD" >> "$ENV_FILE_NESTJS" - echo "POSTGRES_DB=\$POSTGRES_DB" >> "$ENV_FILE_NESTJS" - echo "POSTGRES_HOST=\$POSTGRES_HOST" >> "$ENV_FILE_NESTJS" - echo "POSTGRES_PORT=\$POSTGRES_PORT" >> "$ENV_FILE_NESTJS" - # Connection to 42 - echo "In the next steps, we'll need to enter the client secret and client id of the 42 api" - read -p "Enter the client id of the 42 api : " CLIENT_ID - echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_NESTJS" - read -p "Enter the client secret of the 42 api : " CLIENT_SECRET - echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_NESTJS" - FT_CALLBACK="http://\$WEBSITE_HOST:\$WEBSITE_PORT/api/v2/auth/redirect" - echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_NESTJS" - # Other configs - echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS" - echo "PORT=3000" >> "$ENV_FILE_NESTJS" - echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_NESTJS" - echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS" - - -# it's finished ! -# echo "The environment has been created successfully. You can now wait for the docker to build the project." diff --git a/srcs/.env b/srcs/.env deleted file mode 100644 index f237415c..00000000 --- a/srcs/.env +++ /dev/null @@ -1,12 +0,0 @@ -NODE_ENV=development -WEBSITE_HOST=transcendance -WEBSITE_PORT=8080 -POSTGRES_USER=postgres -#if change postgres pswd, do make destroy -POSTGRES_PASSWORD=m7V8CkL+wl+SU1GagenTWP3oyPJx8JJG+tHRiENxoZQ= -POSTGRES_DB=transcendance_db -POSTGRES_HOST=postgresql -POSTGRES_PORT=5432 -REDIS_HOST=redis -REDIS_PORT=6379 -REDIS_PASSWORD=JKDf9vhE4bb5+JW0CvRXVJ2rcV33Bs1MGcQmCxdL+Qs= diff --git a/srcs/docker-compose.yml b/srcs/docker-compose.yml index dedd380f..3d6fa9c2 100644 --- a/srcs/docker-compose.yml +++ b/srcs/docker-compose.yml @@ -5,23 +5,28 @@ services: context: ./requirements/nestjs target: development dockerfile: Dockerfile - args: - - NODE_ENV=${NODE_ENV} - - WEBSITE_HOST=${WEBSITE_HOST} - - WEBSITE_PORT=${WEBSITE_PORT} - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - - POSTGRES_DB=${POSTGRES_DB} - - POSTGRES_HOST=${POSTGRES_HOST} - - POSTGRES_PORT=${POSTGRES_PORT} + environment: + POSTGRES_USER: "${POSTGRES_USER}" + POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" + POSTGRES_DB: "${POSTGRES_DB}" + POSTGRES_HOST: "${POSTGRES_HOST}" + POSTGRES_PORT: "${POSTGRES_PORT}" + NODE_ENV: "${NODE_ENV}" + WEBSITE_HOST: "${WEBSITE_HOST}" + WEBSITE_PORT: "${WEBSITE_PORT}" + REDIS_HOST: "${REDIS_HOST}" + REDIS_PORT: "${REDIS_PORT}" + FORTYTWO_CLIENT_ID: "${FORTYTWO_CLIENT_ID}" + FORTYTWO_CLIENT_SECRET : "${FORTYTWO_CLIENT_SECRET}" + FORTYTWO_CALLBACK_URL: "${FORTYTWO_CALLBACK_URL}" + COOKIE_SECRET: "${COOKIE_SECRET}" + TWO_FACTOR_AUTHENTICATION_APP_NAME : "${TWO_FACTOR_AUTHENTICATION_APP_NAME}" + TICKET_FOR_PLAYING_GAME_SECRET : "${TICKET_FOR_PLAYING_GAME_SECRET}" + PORT: "${PORT}" volumes: - ./requirements/nestjs/api_back/src:/usr/app/src - ./requirements/nestjs/api_back/test:/usr/app/test/ - nestjs_photos_volume:/usr/app/src/uploads/avatars - env_file: - - .env - environment: - NODE_ENV: "${NODE_ENV}" restart: unless-stopped depends_on: - postgresql @@ -34,6 +39,8 @@ services: dockerfile: Dockerfile environment: NODE_ENV: "${NODE_ENV}" + WEBSITE_HOST: "${WEBSITE_HOST}" + WEBSITE_PORT: "${WEBSITE_PORT}" restart: unless-stopped ports: - "8042:8042" @@ -51,9 +58,9 @@ services: - ./requirements/svelte/api_front/public:/usr/app/public/ ports: - "35729:35729" - env_file: - - .env environment: + WEBSITE_HOST: "${WEBSITE_HOST}" + WEBSITE_PORT: "${WEBSITE_PORT}" NODE_ENV: "${NODE_ENV}" restart: unless-stopped depends_on: diff --git a/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts b/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts index 322b845d..24988b86 100644 --- a/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts +++ b/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts @@ -48,7 +48,10 @@ export class GameSession { timeout += c.newRoundDelay*0.5; }); } - resume(s: GameSession) { + resume(s?: GameSession) + { + if (!s) { s = this; } + s.playersMap.forEach( (client) => { client.socket.on("message", clientInputListener); }); @@ -59,7 +62,10 @@ export class GameSession { s.playersUpdateInterval = setInterval(s._playersUpdate, c.playersUpdateIntervalMS, s); s.spectatorsUpdateInterval = setInterval(s._spectatorsUpdate, c.spectatorsUpdateIntervalMS, s); } - pause(s: GameSession) { + pause(s?: GameSession) + { + if (!s) { s = this; } + s.playersMap.forEach( (client) => { client.socket.off("message", clientInputListener); }); @@ -68,6 +74,19 @@ export class GameSession { clearInterval(s.playersUpdateInterval); clearInterval(s.spectatorsUpdateInterval); } + destroy(s?: GameSession) + { + if (!s) { s = this; } + + s.pause(); + + s.spectatorsMap.forEach((client) => { + clientTerminate(client); + }); + s.playersMap.forEach((client) => { + clientTerminate(client); + }); + } instantInputDebug(client: ClientPlayer) { this._handleInput(c.fixedDeltaTime, client); } @@ -135,11 +154,12 @@ export class GameSession { else if (ball.pos.x < 0 - ball.width) { ++gc.scoreRight; } + const scoreUpdate = new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight); this.playersMap.forEach( (client) => { - client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); + client.socket.send(JSON.stringify(scoreUpdate)); }); this.spectatorsMap.forEach( (client) => { - client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); + client.socket.send(JSON.stringify(scoreUpdate)); }); } private _playersUpdate(s: GameSession) { @@ -148,9 +168,9 @@ export class GameSession { s.lastStateSnapshot.lastInputId = client.lastInputId; client.socket.send(JSON.stringify(s.lastStateSnapshot)); }); + s.lastStateSnapshot.lastInputId = 0; } private _spectatorsUpdate(s: GameSession) { - s.lastStateSnapshot.lastInputId = 0; s.spectatorsMap.forEach( (client) => { client.socket.send(JSON.stringify(s.lastStateSnapshot)); }); @@ -200,31 +220,40 @@ export class GameSession { ball.speed = ball.baseSpeed; ball.ballInPlay = true; } - private _checkDisconnexions() { + private _checkDisconnexions() + { if (this.playersMap.size !== 2) { this.matchEnded = true; - if (this.playersMap.size != 0) - { - console.log("Forfeit Ending"); - const gc = this.components; - const luckyWinner: ClientPlayer = this.playersMap.values().next().value; - if (luckyWinner.racket === gc.playerLeft) { - this._matchEnd(en.PlayerSide.left, true); - } - else { - this._matchEnd(en.PlayerSide.right, true); - } + if (this.playersMap.size != 0) { + this._forfeit(); + } + else { + // WIP: envoyer un truc à Nest ? Genre "match draw" + this.destroy(); } return true; } return false; } + private _forfeit() + { + this.matchEnded = true; + console.log("Forfeit Ending"); + const gc = this.components; + const luckyWinner: ClientPlayer = this.playersMap.values().next().value; + if (luckyWinner.racket === gc.playerLeft) { + this._matchEnd(en.PlayerSide.left, true); + } + else { + this._matchEnd(en.PlayerSide.right, true); + } + } + private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false) { this.matchEnded = true; - let eventEnd: ev.EventMatchEnd; - eventEnd = new ev.EventMatchEnd(winner, forfeit_flag); + const eventEnd = new ev.EventMatchEnd(winner, forfeit_flag); this.playersMap.forEach( (client) => { client.socket.send(JSON.stringify(eventEnd)); }); @@ -232,7 +261,21 @@ export class GameSession { client.socket.send(JSON.stringify(eventEnd)); }); + // TODO: mettre à jour la route pour gerer les forfaits (actuellement le plus haut score gagne par defaut) const gc = this.components; + console.log("================================= MATCH ENDED"); + if (forfeit_flag) { + if (winner === en.PlayerSide.left) + { + gc.scoreLeft = 3 + gc.scoreRight = 0 + } + else + { + gc.scoreLeft = 0 + gc.scoreRight = 3 + } + } await fetch(c.addressBackEnd + "/game/gameserver/updategame", { method: "POST", @@ -246,15 +289,7 @@ export class GameSession { }) }); - const gameSession = this; - setTimeout(function kickRemainingClients() { - gameSession.spectatorsMap.forEach((client) => { - clientTerminate(client); - }); - gameSession.playersMap.forEach((client) => { - clientTerminate(client); - }); - }, 15000); + setTimeout(this.destroy, 15000, this); // logs if (winner === en.PlayerSide.left) { diff --git a/srcs/requirements/game_server/game_back/src/server/wsServer.ts b/srcs/requirements/game_server/game_back/src/server/wsServer.ts index d28fcff9..99fc6597 100644 --- a/srcs/requirements/game_server/game_back/src/server/wsServer.ts +++ b/srcs/requirements/game_server/game_back/src/server/wsServer.ts @@ -14,7 +14,6 @@ import * as c from "./constants.js" import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js" import { GameSession } from "./class/GameSession.js" import { shortId } from "./utils.js"; -import { gameSessionIdPLACEHOLDER } from "./constants.js"; const wsPort = 8042; export const wsServer = new WebSocketServer({host: "0.0.0.0", port: wsPort, path: "/pong"}); @@ -23,12 +22,12 @@ const matchmakingMap: Map = new Map; // socket.id/ClientPl const privateMatchmakingMap: Map = new Map; // socket.id/ClientPlayer (duplicates with clientsMap) const gameSessionsMap: Map = new Map; // GameSession.id(url)/GameSession -wsServer.on("connection", connectionListener); -wsServer.on("error", errorListener); -wsServer.on("close", closeListener); +wsServer.on("connection", serverConnectionListener); +wsServer.on("error", serverErrorListener); +wsServer.on("close", serverCloseListener); -function connectionListener(socket: WebSocket, request: IncomingMessage) +function serverConnectionListener(socket: WebSocket, request: IncomingMessage) { const id = uuidv4(); const client = new Client(socket, id); @@ -40,7 +39,19 @@ function connectionListener(socket: WebSocket, request: IncomingMessage) console.log(`client ${shortId(client.id)} is alive`); }); - socket.on("message", function log(data: string) { + socket.on("close", function removeClient() { + clientTerminate(client); + }); + + socket.on("error", function errorLog(this: WebSocket, err: Error) { + console.log(`error socket ${shortId(this.id)}:`); + console.log(`${err.name}: ${err.message}`); + if (err.stack) { + console.log(`err.stack: ${err.stack}`); + } + }); + + socket.on("message", function messageLog(data: string) { try { const event: ev.ClientEvent = JSON.parse(data); if (event.type === en.EventTypes.clientInput) { @@ -61,13 +72,11 @@ async function clientAnnounceListener(this: WebSocket, data: string) const msg : ev.ClientAnnounce = JSON.parse(data); if (msg.type === en.EventTypes.clientAnnounce) { - // TODO: reconnection with msg.clientId ? - // "/pong" to play, "/pong?ID_OF_A_GAMESESSION" to spectate (or something like that) + // BONUS: reconnection with msg.clientId ? if (msg.role === en.ClientRole.player) { const announce: ev.ClientAnnouncePlayer = msg; - // WIP nest, fetch token validation const body = { playerOneUsername: announce.username, playerTwoUsername: "", @@ -88,7 +97,7 @@ async function clientAnnounceListener(this: WebSocket, data: string) }); if (!response.ok) { - this.send(JSON.stringify( new ev.EventError((await response.json()).message))); + this.send(JSON.stringify( new ev.EventError((await response.json()).message) )); clientTerminate(clientsMap.get(this.id)); return; } @@ -96,10 +105,13 @@ async function clientAnnounceListener(this: WebSocket, data: string) const player = clientsMap.get(this.id) as ClientPlayer; player.matchOptions = announce.matchOptions; player.token = announce.token; - announce.isInvitedPerson ? player.username = announce.playerTwoUsername : player.username = announce.username; + player.username = announce.username; this.send(JSON.stringify( new ev.EventAssignId(this.id) )); // unused this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) )); if (announce.privateMatch) { + if (announce.isInvitedPerson) { + player.username = announce.playerTwoUsername; + } privateMatchmaking(player); } else { @@ -111,13 +123,14 @@ async function clientAnnounceListener(this: WebSocket, data: string) const announce: ev.ClientAnnounceSpectator = msg; const gameSession = gameSessionsMap.get(announce.gameSessionId); if (!gameSession) { - this.send(JSON.stringify( new ev.EventError("invalid gameSessionId"))); + this.send(JSON.stringify( new ev.EventError("invalid gameSessionId") )); clientTerminate(clientsMap.get(this.id)); return; } const spectator = clientsMap.get(this.id) as ClientSpectator; spectator.gameSession = gameSession; gameSession.spectatorsMap.set(spectator.id, spectator); + spectator.socket.once("message", spectatorReadyConfirmationListener); this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); } } @@ -213,7 +226,7 @@ function privateMatchmaking(player: ClientPlayer) function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions) { - // const id = gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR + // const id = c.gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR const id = uuidv4(); const gameSession = new GameSession(id, matchOptions); gameSessionsMap.set(id, gameSession); @@ -263,7 +276,6 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string) gameSession.unreadyPlayersMap.delete(this.id); if (gameSession.unreadyPlayersMap.size === 0) { - // WIP nest , send gameSession.id const gameSessionPlayersIterator = gameSession.playersMap.values(); const body = { gameServerIdOfTheMatch : gameSession.id, @@ -330,6 +342,28 @@ export function clientInputListener(this: WebSocket, data: string) } } +function spectatorReadyConfirmationListener(this: WebSocket, data: string) +{ + try { + const msg : ev.ClientEvent = JSON.parse(data); + if (msg.type === en.EventTypes.clientSpectatorReady) + { + const client = clientsMap.get(this.id); + const gameSession = client.gameSession; + const scoreUpdate = new ev.EventScoreUpdate(gameSession.components.scoreLeft, gameSession.components.scoreRight); + this.send(JSON.stringify(scoreUpdate)); + } + else { + console.log("Invalid spectatorReadyConfirmation"); + } + return; + } + catch (e) { + console.log("Invalid JSON (spectatorReadyConfirmationListener)"); + } + this.once("message", spectatorReadyConfirmationListener); +} + //////////// //////////// @@ -363,11 +397,10 @@ export function clientTerminate(client: Client) if (client.gameSession) { client.gameSession.playersMap.delete(client.id); + client.gameSession.spectatorsMap.delete(client.id); if (client.gameSession.playersMap.size === 0) { - clearInterval(client.gameSession.playersUpdateInterval); - clearInterval(client.gameSession.spectatorsUpdateInterval); - clearInterval(client.gameSession.gameLoopInterval); + client.gameSession.destroy(); gameSessionsMap.delete(client.gameSession.id); } } @@ -381,13 +414,13 @@ export function clientTerminate(client: Client) } -function closeListener() +function serverCloseListener() { clearInterval(pingInterval); } -function errorListener(error: Error) +function serverErrorListener(error: Error) { console.log("Error: " + JSON.stringify(error)); } diff --git a/srcs/requirements/game_server/game_back/src/shared_js/constants.ts b/srcs/requirements/game_server/game_back/src/shared_js/constants.ts index 44c282c2..18713ae4 100644 --- a/srcs/requirements/game_server/game_back/src/shared_js/constants.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/constants.ts @@ -26,5 +26,5 @@ export const movingWallPosMax = Math.floor(w*0.12); export const movingWallSpeed = Math.floor(w*0.08); -export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER -// for testing, force gameSession.id in wsServer.ts->matchmaking() \ No newline at end of file +export const gameSessionIdPLACEHOLDER = "match-id-test-42"; // TESTING SPECTATOR PLACEHOLDER +// for testing, force gameSession.id in wsServer.ts->createGameSession() diff --git a/srcs/requirements/game_server/game_back/src/shared_js/enums.ts b/srcs/requirements/game_server/game_back/src/shared_js/enums.ts index b86571e5..6d54e139 100644 --- a/srcs/requirements/game_server/game_back/src/shared_js/enums.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/enums.ts @@ -19,6 +19,7 @@ export enum EventTypes { // Client clientAnnounce, clientPlayerReady, + clientSpectatorReady, clientInput, } diff --git a/srcs/requirements/nestjs/Dockerfile b/srcs/requirements/nestjs/Dockerfile index 8d600d69..d4228c0b 100644 --- a/srcs/requirements/nestjs/Dockerfile +++ b/srcs/requirements/nestjs/Dockerfile @@ -2,28 +2,9 @@ FROM node:alpine AS development WORKDIR /usr/app -ARG NODE_ENV -ARG WEBSITE_HOST -ARG WEBSITE_PORT -ARG POSTGRES_USER -ARG POSTGRES_PASSWORD -ARG POSTGRES_DB -ARG POSTGRES_HOST -ARG POSTGRES_PORT - COPY ./api_back ./ COPY ./api_back/src/uploads/avatars/default.png ./uploads/avatars/default.png -COPY ./api_back/.env ./.env -RUN npm install -RUN sed -i "s/\$NODE_ENV/${NODE_ENV}/g" ./.env && \ - sed -i "s/\$WEBSITE_HOST/${WEBSITE_HOST}/g" ./.env && \ - sed -i "s/\$WEBSITE_PORT/${WEBSITE_PORT}/g" ./.env && \ - sed -i "s/\$POSTGRES_USER/${POSTGRES_USER}/g" ./.env && \ - sed -i "s/\$POSTGRES_PASSWORD/${POSTGRES_PASSWORD}/g" ./.env && \ - sed -i "s/\$POSTGRES_DB/${POSTGRES_DB}/g" ./.env && \ - sed -i "s/\$POSTGRES_HOST/${POSTGRES_HOST}/g" ./.env && \ - sed -i "s/\$POSTGRES_PORT/${POSTGRES_PORT}/g" ./.env +RUN npm i CMD [ "npm", "run", "start:dev" ] - diff --git a/srcs/requirements/nestjs/api_back/.env b/srcs/requirements/nestjs/api_back/.env deleted file mode 100644 index bdcb3f01..00000000 --- a/srcs/requirements/nestjs/api_back/.env +++ /dev/null @@ -1,15 +0,0 @@ -NODE_ENV=$NODE_ENV -WEBSITE_HOST=$WEBSITE_HOST -WEBSITE_PORT=$WEBSITE_PORT -POSTGRES_USER=$POSTGRES_USER -POSTGRES_PASSWORD=$POSTGRES_PASSWORD -POSTGRES_DB=$POSTGRES_DB -POSTGRES_HOST=$POSTGRES_HOST -POSTGRES_PORT=$POSTGRES_PORT -FORTYTWO_CLIENT_ID=u-s4t2ud-49dc7b539bcfe1acb48b928b2b281671c99fc5bfab1faca57a536ab7e0075500 -FORTYTWO_CLIENT_SECRET=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 -FORTYTWO_CALLBACK_URL=http://$WEBSITE_HOST:$WEBSITE_PORT/api/v2/auth/redirect -COOKIE_SECRET=wABcR5SytbN4kiPa_4Y8IhhdLDb4Yn0EvVvOPZRQf4Q= -PORT=3000 -TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance -TICKET_FOR_PLAYING_GAME_SECRET=hvt8PQo3o+BHimS0RO5viln65yF9zMIuZFEmhxQGdik= diff --git a/srcs/requirements/nestjs/api_back/package-lock.json b/srcs/requirements/nestjs/api_back/package-lock.json index 2085d3b6..c3e88cfb 100644 --- a/srcs/requirements/nestjs/api_back/package-lock.json +++ b/srcs/requirements/nestjs/api_back/package-lock.json @@ -19,7 +19,6 @@ "@nestjs/typeorm": "^9.0.1", "@nestjs/websockets": "^9.2.1", "@types/express-session": "^1.17.5", - "@types/redis": "^4.0.11", "@types/validator": "^13.7.9", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", @@ -48,7 +47,7 @@ "@types/express": "^4.17.13", "@types/jest": "28.1.8", "@types/multer": "^1.4.7", - "@types/node": "^16.0.0", + "@types/node": "^16.18.11", "@types/passport-local": "^1.0.34", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", @@ -1694,65 +1693,6 @@ "@nestjs/core": "^9.0.0" } }, - "node_modules/@nestjs/platform-express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, "node_modules/@nestjs/platform-socket.io": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz", @@ -1787,11 +1727,6 @@ "node": ">=10.0.0" } }, - "node_modules/@nestjs/platform-socket.io/node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, "node_modules/@nestjs/schematics": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz", @@ -1960,11 +1895,6 @@ } } }, - "node_modules/@nestjs/websockets/node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2381,9 +2311,9 @@ } }, "node_modules/@types/node": { - "version": "16.18.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", - "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" + "version": "16.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", + "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -2437,15 +2367,6 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, - "node_modules/@types/redis": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz", - "integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==", - "deprecated": "This is a stub types definition. redis provides its own type definitions, so you do not need this installed.", - "dependencies": { - "redis": "*" - } - }, "node_modules/@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -3372,11 +3293,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -4070,14 +3986,6 @@ "node": ">=12" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6533,25 +6441,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -6630,11 +6519,6 @@ "optional": true, "peer": true }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, "node_modules/lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -6642,31 +6526,6 @@ "optional": true, "peer": true }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -6679,11 +6538,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -6720,6 +6574,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -8300,6 +8155,7 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -11132,11 +10988,6 @@ "socket.io-adapter": "~2.4.0", "socket.io-parser": "~4.2.0" } - }, - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" } } }, @@ -11250,13 +11101,6 @@ "iterare": "1.2.1", "object-hash": "3.0.0", "tslib": "2.4.1" - }, - "dependencies": { - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - } } }, "@nodelib/fs.scandir": { @@ -11642,9 +11486,9 @@ } }, "@types/node": { - "version": "16.18.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", - "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" + "version": "16.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", + "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" }, "@types/parse-json": { "version": "4.0.0", @@ -11698,14 +11542,6 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, - "@types/redis": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz", - "integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==", - "requires": { - "redis": "*" - } - }, "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -12397,11 +12233,6 @@ "ieee754": "^1.1.13" } }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -12906,14 +12737,6 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz", "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==" }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -14766,25 +14589,6 @@ "universalify": "^2.0.0" } }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -14845,11 +14649,6 @@ "optional": true, "peer": true }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -14857,31 +14656,6 @@ "optional": true, "peer": true }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -14894,11 +14668,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -14925,6 +14694,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { "yallist": "^4.0.0" } @@ -16078,6 +15848,7 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } diff --git a/srcs/requirements/nestjs/api_back/package.json b/srcs/requirements/nestjs/api_back/package.json index a75c646c..4e8c4666 100644 --- a/srcs/requirements/nestjs/api_back/package.json +++ b/srcs/requirements/nestjs/api_back/package.json @@ -59,7 +59,7 @@ "@types/express": "^4.17.13", "@types/jest": "28.1.8", "@types/multer": "^1.4.7", - "@types/node": "^16.0.0", + "@types/node": "^16.18.11", "@types/passport-local": "^1.0.34", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", diff --git a/srcs/requirements/nestjs/api_back/src/auth/42/authentication.controller.ts b/srcs/requirements/nestjs/api_back/src/auth/42/authentication.controller.ts index 6746e911..44de4932 100644 --- a/srcs/requirements/nestjs/api_back/src/auth/42/authentication.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/auth/42/authentication.controller.ts @@ -37,10 +37,10 @@ export class AuthenticationController { const user : User = request.user if (user.isEnabledTwoFactorAuth === false || user.isTwoFactorAuthenticated === true){ console.log('ON VA VERS PROFILE'); - return response.status(200).redirect('http://transcendance:8080/#/profile'); + return response.status(200).redirect('http://' + process.env.WEBSITE_HOST + ':' + process.env.WEBSITE_PORT + '/#/profile'); } console.log('ON VA VERS 2FA') - return response.status(200).redirect('http://transcendance:8080/#/2fa'); + return response.status(200).redirect('http://' + process.env.WEBSITE_HOST + ':' + process.env.WEBSITE_PORT + '/#/2fa'); } /** @@ -83,6 +83,6 @@ export class AuthenticationController { throw new UnauthorizedException('Wrong Code.'); await this.userService.authenticateUserWith2FA(request.user.id); console.log('ON REDIRIGE'); - return response.status(200).redirect('http://transcendance:8080/#/profile'); + return response.status(200).redirect('http://' + process.env.WEBSITE_HOST + ':' + process.env.WEBSITE_PORT + '/#/profile'); } } diff --git a/srcs/requirements/nestjs/api_back/src/chat/chat.gateway.ts b/srcs/requirements/nestjs/api_back/src/chat/chat.gateway.ts index 6b54710e..c6d88417 100644 --- a/srcs/requirements/nestjs/api_back/src/chat/chat.gateway.ts +++ b/srcs/requirements/nestjs/api_back/src/chat/chat.gateway.ts @@ -4,7 +4,7 @@ import { WebSocketServer, MessageBody, OnGatewayConnection, - OnGatewayDisconnect, + OnGatewayDisconnect, } from '@nestjs/websockets'; import { UsersService } from 'src/users/users.service'; import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto'; @@ -32,9 +32,8 @@ export class ChatGateway async handleDisconnect(client) { console.log('---- client disconnected :', client.id); } - /* - */ - @SubscribeMessage('test_users') + + @SubscribeMessage('') handleMessage(): void { const paginationQuery = new PaginationQueryDto(); const users = this.usersService.findAll(paginationQuery); diff --git a/srcs/requirements/nestjs/api_back/src/chat/chat.module.ts b/srcs/requirements/nestjs/api_back/src/chat/chat.module.ts index 53188366..d67a4b9d 100644 --- a/srcs/requirements/nestjs/api_back/src/chat/chat.module.ts +++ b/srcs/requirements/nestjs/api_back/src/chat/chat.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +//import { Module } from '@nestjs/common'; //import { TypeOrmModule } from '@nestjs/typeorm'; //import { FriendshipService } from './friendship.service'; //import { FriendshipController } from './friendship.controller'; @@ -12,5 +12,5 @@ import { Module } from '@nestjs/common'; // exports: [FriendshipService], //}) -export class FriendshipsModule {} +//export class FriendshipsModule {} diff --git a/srcs/requirements/nestjs/api_back/src/chat/chat.service.ts b/srcs/requirements/nestjs/api_back/src/chat/chat.service.ts index e69de29b..80b3864d 100644 --- a/srcs/requirements/nestjs/api_back/src/chat/chat.service.ts +++ b/srcs/requirements/nestjs/api_back/src/chat/chat.service.ts @@ -0,0 +1,204 @@ +//import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; +//import { InjectRepository } from '@nestjs/typeorm'; +//import { User } from 'src/users/entities/user.entity'; +//import { Repository } from 'typeorm'; +//import { CreateFriendshipDto } from './dto/create-friendship.dto'; +//import { Friendship, FriendshipStatus } from './entities/friendship.entity'; + +/* +@Injectable() +export class FriendshipService { + + constructor( + @InjectRepository(Friendship) + private readonly friendshipRepository: Repository, + @InjectRepository(User) + private readonly userRepository: Repository, + ) { } + + + async findOneFriend(friendshipId: string, username: string) { + const friendship = await this.friendshipRepository.find({ where: { id: +friendshipId, senderUsername: username, status: FriendshipStatus.ACCEPTED } }); + if (!friendship) + throw new HttpException(`The requested friend not found.`, HttpStatus.NOT_FOUND); + return friendship; + } + + async findOneBlocked(friendshipId: string, username: string) { + const friendship = await this.friendshipRepository.find({ where: { id: +friendshipId, senderUsername: username, status: FriendshipStatus.BLOCKED } }); + if (!friendship) + throw new HttpException(`The requested blocked not found.`, HttpStatus.NOT_FOUND); + return friendship; + } + + async findAllFriends(username: string) { + const friendship = await this.friendshipRepository + .createQueryBuilder('friendship') + .where('friendship.status = :status', { status: FriendshipStatus.ACCEPTED }) + .andWhere('friendship.receiverUsername = :addressee', { addressee: username }) + .orWhere('friendship.senderUsername = :requester', { requester: username }) + .andWhere('friendship.status = :status', { status: FriendshipStatus.ACCEPTED }) + .getMany(); + for (const friend of friendship) + console.log("FRIENDSHIP : " + friend.status); + return friendship; + } + + async findAllBlockedFriends(username: string) { + const friendships : Friendship[] = await this.friendshipRepository + .createQueryBuilder('friendship') + .where('friendship.senderUsername = :requestee', { requestee: username }) + .andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED }) + .getMany(); + let partialFriendship : Partial[] = []; + for (const friendship of friendships) { + partialFriendship.push({id: friendship.id, date: friendship.date, senderUsername: friendship.senderUsername, receiverUsername: friendship.receiverUsername, status: friendship.status}); + } + return partialFriendship; + } + + async findAllPendantRequestsForFriendship(username: string) { + const friendship = await this.friendshipRepository + .createQueryBuilder('friendship') + .where('friendship.senderUsername = :requestee', { requestee: username }) + .andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED }) + .getMany(); + let partialFriendship : Partial[] = []; + for (const friend of friendship) { + console.log("FRIENDSHIP : " + friend); + partialFriendship.push({id: friend.id, senderUsername: friend.senderUsername, receiverUsername: friend.receiverUsername, status: friend.status}); + } + console.log("Pendant requests : " + partialFriendship); + return partialFriendship; + } + + async findAllReceivedRequestsForFriendship(username: string) { + const friendship = await this.friendshipRepository + .createQueryBuilder('friendship') + .where('friendship.receiverUsername = :addressee', { addressee: username }) + .andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED }) + .getMany(); + let partialFriendship : Partial[] = []; + for (const friend of friendship) { + partialFriendship.push({id: friend.id, senderUsername: friend.senderUsername, receiverUsername: friend.receiverUsername, status: friend.status}); + } + return partialFriendship; + } + + async create(createFriendshipDto: CreateFriendshipDto, creator : User) : Promise > { + console.log("DTO : \n") + console.log({...createFriendshipDto}) + const receiver = await this.userRepository.findOneBy({username: createFriendshipDto.receiverUsername}); + if (!receiver) + throw new HttpException(`The addressee does not exist.`, HttpStatus.NOT_FOUND); + if (createFriendshipDto.status !== FriendshipStatus.REQUESTED && createFriendshipDto.status !== FriendshipStatus.BLOCKED) + throw new HttpException(`The status is not valid.`, HttpStatus.NOT_FOUND); + const friendship = await this.friendshipRepository.findOneBy({ sender: creator, receiver: receiver }); + if (friendship) { + if (friendship.status && friendship.status === FriendshipStatus.ACCEPTED) + throw new HttpException(`The friendship request has already been accepted.`, HttpStatus.OK); + else if (friendship.status && friendship.status === FriendshipStatus.REQUESTED) + throw new HttpException(`The friendship request has already been sent the ${friendship.date}.`, HttpStatus.OK); + else if (friendship.status && friendship.status === FriendshipStatus.BLOCKED) + throw new HttpException(`We can't do that`, HttpStatus.OK); + else if (friendship.status && friendship.status === FriendshipStatus.DECLINED) + throw new HttpException(`The request has been declined.`, HttpStatus.OK); + } + const newFriendship = new Friendship(); + newFriendship.sender = creator; + newFriendship.senderUsername = creator.username; + newFriendship.receiver = receiver; + newFriendship.receiverUsername = receiver.username; + newFriendship.status = createFriendshipDto.status; + const savedFriendship = this.friendshipRepository.save(newFriendship); + const partialFriendship : Partial = { + id : (await savedFriendship).id, + date : (await savedFriendship).date, + receiverUsername: (await savedFriendship).receiverUsername, + status : (await savedFriendship).status + } + console.log({...partialFriendship}) + return partialFriendship; + } + + async acceptFriendship(relationshipId: string, user: User) { + const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId }); + if (!relation) + throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND); + if (relation.sender.id === user.id) { + throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND); + } + relation.status = FriendshipStatus.ACCEPTED; + const savedFriendship = this.friendshipRepository.save(relation); + const partialFriendship : Partial = { + id : (await savedFriendship).id, + date : (await savedFriendship).date, + receiverUsername: (await savedFriendship).receiverUsername, + status : (await savedFriendship).status + } + return partialFriendship; + } + + async declineFriendship(relationshipId: string, user: User) { + const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId }); + if (!relation) + throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND); + if (relation.sender.id === user.id) { + throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND); + } + relation.status = FriendshipStatus.DECLINED; + const savedFriendship = this.friendshipRepository.save(relation); + const partialFriendship : Partial = { + id : (await savedFriendship).id, + date : (await savedFriendship).date, + receiverUsername: (await savedFriendship).receiverUsername, + status : (await savedFriendship).status + } + return partialFriendship + } + + async blockFriendship(relationshipId: string, user: User) { + const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId }); + if (!relation) + throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND); + if (relation.sender.id === user.id) { + throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND); + } + relation.status = FriendshipStatus.BLOCKED; + const savedFriendship = this.friendshipRepository.save(relation); + const partialFriendship : Partial = { + id : (await savedFriendship).id, + date : (await savedFriendship).date, + receiverUsername: (await savedFriendship).receiverUsername, + status : (await savedFriendship).status + } + return partialFriendship + } + + async removeFriendship(relationshipId: string, user : User) { + const friendship = await this.friendshipRepository.findOneBy({ id: +relationshipId }); + if (!friendship) + throw new HttpException(`Your friend could not be deleted.`, HttpStatus.NOT_FOUND); + if (friendship.sender.id !== user.id || friendship.receiver.id !== user.id) { + throw new HttpException(`You can't do that.`, HttpStatus.FORBIDDEN); + } + return this.friendshipRepository.remove(friendship); + } + + async findIfUserIsBlockedOrHasBlocked(userConnectedId: string, userToFindId: string) { + console.log("finding if user is blocked") + const friendship = await this.friendshipRepository + .createQueryBuilder('friendship') + .where('friendship.senderUsername = :requestee', { requestee: userConnectedId }) + .orWhere('friendship.senderUsername = :requesteeBis', { requesteeBis: userToFindId }) + .andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED }) + .getOne(); + if (friendship) { + console.log('we are blocked in friendship.service') + return true; + } + return false; + } +} +*/ diff --git a/srcs/requirements/nestjs/api_back/src/common/constants/constants.ts b/srcs/requirements/nestjs/api_back/src/common/constants/constants.ts index bd208814..350ad38b 100644 --- a/srcs/requirements/nestjs/api_back/src/common/constants/constants.ts +++ b/srcs/requirements/nestjs/api_back/src/common/constants/constants.ts @@ -24,5 +24,13 @@ export const storageForAvatar = { const extension : string = MIME_TYPES[file.mimetype]; cb(null, `${filename}${extension}`); } - }) + }), + fileFilter: (req, file, cb) => { + if (file.mimetype === 'image/png' || file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg') { + cb(null, true); + } + else { + cb(null, false); + } + } } diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts index 1af581b0..11386c4b 100644 --- a/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts +++ b/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts @@ -17,6 +17,9 @@ export class Game { @Column({default : 0, nullable : true}) playerTwoUsernameResult : number + @Column({default : 0}) + gameOptions: number + @Column({unique : true}) gameServerIdOfTheMatch: string diff --git a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts index b6b3770b..b393eaf5 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts @@ -13,6 +13,14 @@ export class GameController { constructor (private readonly gameService : GameService) { } + @Get('match/all') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async getMatchesForSpectator() + { + return this.gameService.getMatchesForSpectator(); + } + @Get('ranking') @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) diff --git a/srcs/requirements/nestjs/api_back/src/game/game.service.ts b/srcs/requirements/nestjs/api_back/src/game/game.service.ts index f00c941d..437abd5e 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.service.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.service.ts @@ -28,6 +28,21 @@ export class GameService { private readonly friendShipService : FriendshipService ) { } + async getMatchesForSpectator() { + const games = await this.gameRepository.createQueryBuilder("game") + .where('game.isMatchIsFinished = :isMatchIsFinished', {isMatchIsFinished : false}) + .getMany(); + const gamesToReturn : Partial[] = [] + for (const game of games) + { + gamesToReturn.push({gameServerIdOfTheMatch : game.gameServerIdOfTheMatch, + gameOptions : game.gameOptions, playerOneUsername : game.playerOneUsername, + playerTwoUsername : game.playerTwoUsername}) + console.log("Is match is finished : " + game.isMatchIsFinished) + } + return gamesToReturn; + } + async getRankingForAllUsers(currentUser : User) { const users = await this.userRepository.createQueryBuilder("user") .leftJoinAndSelect("user.stats", "stats") @@ -255,6 +270,8 @@ export class GameService { game.playerOneUsernameResult = updateGameDto.playerOneUsernameResult game.playerTwoUsernameResult = updateGameDto.playerTwoUsernameResult this.gameRepository.save(game); + console.log("On a sauvegardé la partie. Game :") + console.log(game) const playerOne = await this.userRepository.findOneBy({username : game.playerOneUsername}) const playerTwo = await this.userRepository.findOneBy({username : game.playerTwoUsername}) if (!playerOne || !playerTwo) diff --git a/srcs/requirements/nestjs/api_back/src/main.ts b/srcs/requirements/nestjs/api_back/src/main.ts index 78cb852c..e9ea8426 100644 --- a/srcs/requirements/nestjs/api_back/src/main.ts +++ b/srcs/requirements/nestjs/api_back/src/main.ts @@ -8,7 +8,7 @@ import * as connectRedis from 'connect-redis'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: true }); - const port = process.env.PORT || 3001; + const port = process.env.PORT || 3000; const client = redis.createClient( { socket: { host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT) }, @@ -50,6 +50,6 @@ async function bootstrap() { ); app.use(passport.initialize()); app.use(passport.session()); - await app.listen(port, () => { console.log(`Listening on port ${port}`); }); + await app.listen(port, () => { console.log(`Listening on port ${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}}`); }); } bootstrap(); diff --git a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts index 9b44bc88..e41da191 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts @@ -1,5 +1,5 @@ import { - Body, Controller, Delete, Get, NotFoundException, Param, Patch, Post, Query, Redirect, Req, Res, UploadedFile, UseGuards, UseInterceptors + Body, Controller, Delete, Get, NotFoundException,HttpStatus, Param, Patch, Post, Query, Redirect, Req, Res, UploadedFile, UseGuards, UseInterceptors } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { Response } from 'express'; @@ -31,19 +31,6 @@ export class UsersController { ///////////////////////// RUD ////////////////////////// //////////////////////////////////////////////////////// - /** - * On ne fait de création via une route - * car un utilisateur est crée à la première connexion avec l'Oauth de 42. - */ - - // @UseGuards(AuthenticateGuard) - // @UseGuards(TwoFactorGuard) - // @Get() - // findOne(@Req() req) { - // console.log("Backend Getting current user"); - // return this.usersService.findOne(req.user.id); - // } - @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) @Get() @@ -100,9 +87,14 @@ export class UsersController { @UseGuards(TwoFactorGuard) @Post('avatar') @UseInterceptors(FileInterceptor('file', storageForAvatar)) - uploadAvatar(@UploadedFile() file, @Req() request){ + uploadAvatar(@UploadedFile() file, @Req() request, @Res() res){ const user : User = request.user; - this.usersService.updateAvatar(user.id, file.filename); + if (file) + { + this.usersService.updateAvatar(user.id, file.filename); + return res.status(HttpStatus.OK).json({message : "Avatar updated"}); + } + return res.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).json({message : "Unsupported media type. Please use a valid image file."}); } @UseGuards(AuthenticateGuard) diff --git a/srcs/requirements/nginx/conf/default.conf b/srcs/requirements/nginx/conf/default.conf index 92c95f34..9f24d894 100644 --- a/srcs/requirements/nginx/conf/default.conf +++ b/srcs/requirements/nginx/conf/default.conf @@ -1,7 +1,6 @@ server { - - listen 8080 default_server; - listen [::]:8080 default_server; + listen 8080; + listen [::]:8080; server_name transcendance; location /api/v2 { @@ -17,7 +16,7 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; + proxy_set_header Connection "Upgrade"; proxy_pass http://backend_dev:5000/chat; } @@ -43,7 +42,6 @@ server { } server { - listen 35729 default_server; listen [::]:35729 default_server; server_name transcendance; diff --git a/srcs/requirements/svelte/.dockerignore b/srcs/requirements/svelte/.dockerignore index 29c9a005..836f34cf 100644 --- a/srcs/requirements/svelte/.dockerignore +++ b/srcs/requirements/svelte/.dockerignore @@ -8,3 +8,4 @@ !api_front/*.json !api_front/*.html !api_front/*.lock +!api_front/.env diff --git a/srcs/requirements/svelte/api_front/README.md b/srcs/requirements/svelte/api_front/README.md deleted file mode 100644 index 43e08d6a..00000000 --- a/srcs/requirements/svelte/api_front/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# This repo is no longer maintained. Consider using `npm init vite` and selecting the `svelte` option or — if you want a full-fledged app framework and don't mind using pre-1.0 software — use [SvelteKit](https://kit.svelte.dev), the official application framework for Svelte. - ---- - -# svelte app - -This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. - -To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): - -```bash -npx degit sveltejs/template svelte-app -cd svelte-app -``` - -*Note that you will need to have [Node.js](https://nodejs.org) installed.* - - -## Get started - -Install the dependencies... - -```bash -cd svelte-app -npm install -``` - -...then start [Rollup](https://rollupjs.org): - -```bash -npm run dev -``` - -Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. - -By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. - -If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. - -## Building and running in production mode - -To create an optimised version of the app: - -```bash -npm run build -``` - -You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). - - -## Single-page app mode - -By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. - -If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: - -```js -"start": "sirv public --single" -``` - -## Using TypeScript - -This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: - -```bash -node scripts/setupTypeScript.js -``` - -Or remove the script via: - -```bash -rm scripts/setupTypeScript.js -``` - -If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). - -## Deploying to the web - -### With [Vercel](https://vercel.com) - -Install `vercel` if you haven't already: - -```bash -npm install -g vercel -``` - -Then, from within your project folder: - -```bash -cd public -vercel deploy --name my-project -``` - -### With [surge](https://surge.sh/) - -Install `surge` if you haven't already: - -```bash -npm install -g surge -``` - -Then, from within your project folder: - -```bash -npm run build -surge public my-project.surge.sh -``` diff --git a/srcs/requirements/svelte/api_front/old_unused/App_old.svelte b/srcs/requirements/svelte/api_front/old_unused/App_old.svelte deleted file mode 100644 index 4052bae1..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/App_old.svelte +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - diff --git a/srcs/requirements/svelte/api_front/old_unused/Canvas_1st_attempt.svelte b/srcs/requirements/svelte/api_front/old_unused/Canvas_1st_attempt.svelte deleted file mode 100644 index 4d3e6c26..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/Canvas_1st_attempt.svelte +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - diff --git a/srcs/requirements/svelte/api_front/old_unused/Canvas_weird_circles.svelte b/srcs/requirements/svelte/api_front/old_unused/Canvas_weird_circles.svelte deleted file mode 100644 index 330e93f7..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/Canvas_weird_circles.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - - diff --git a/srcs/requirements/svelte/api_front/old_unused/DisplayAUser_backup_copy.svelte b/srcs/requirements/svelte/api_front/old_unused/DisplayAUser_backup_copy.svelte deleted file mode 100644 index 85d8fe4e..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/DisplayAUser_backup_copy.svelte +++ /dev/null @@ -1,112 +0,0 @@ - - -{#if user !== undefined} - -{:else} -

Sorry

-
Failed to load user {aUsername}
-{/if} - - - - \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/old_unused/FlyingPotato.svelte b/srcs/requirements/svelte/api_front/old_unused/FlyingPotato.svelte deleted file mode 100644 index 5f6b544f..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/FlyingPotato.svelte +++ /dev/null @@ -1,24 +0,0 @@ - \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/old_unused/Header.svelte b/srcs/requirements/svelte/api_front/old_unused/Header.svelte deleted file mode 100644 index 3afd24fd..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/Header.svelte +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -
- - Potato Pong Logo - -

Potato Pong

- - -
- - \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/old_unused/Header_Multi_old.svelte b/srcs/requirements/svelte/api_front/old_unused/Header_Multi_old.svelte deleted file mode 100644 index 5439b8c9..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/Header_Multi_old.svelte +++ /dev/null @@ -1,102 +0,0 @@ - - - - - -
-

- Potato Pong Logo -

- -

Potato Pong

- -
- - \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/old_unused/HomePage_old.svelte b/srcs/requirements/svelte/api_front/old_unused/HomePage_old.svelte deleted file mode 100644 index 1b861b0c..00000000 --- a/srcs/requirements/svelte/api_front/old_unused/HomePage_old.svelte +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
- - - - - {#if activeItem === 'Login'} -
- -

Login

-
-
- -
{ errors.username }
-
-
- -
{ errors.password }
-
- - - -
-
-
- {:else if activeItem = 'Create Account'} - -
- -

Create Account

-
-
- -
{ errors.username }
-
-
- -
{ errors.password }
-
- - - -
-
-
- {/if} - - -
- - -