From 89d4150f0efd79c76a63412cd13d0a49c48bae58 Mon Sep 17 00:00:00 2001 From: Zsolt Stenger Date: Sat, 27 Apr 2024 12:48:47 +0200 Subject: [PATCH 1/6] added invite to game option for chat --- Makefile | 2 +- backend/game/test.js | 24 +++++++-------- docker/backend/backend.sh | 4 +-- docker/nginx/config/backend.conf | 4 +-- docker/nginx/config/nginx.conf | 6 ++-- docker/nginx/nginx.sh | 4 +-- docker/nginx/nginx_deployment.sh | 4 +-- frontend/README.md | 2 +- frontend/package.json | 4 +-- frontend/src/pages/Chat.js | 28 ++++++++++++++++- frontend/src/pages/Games/OriginalPong.js | 38 ++++++++++++++---------- 11 files changed, 75 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index 3047336b..6c0889ce 100755 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ all: runb: daphne -b 0.0.0.0 backend.asgi:application -# http://10.12.2.4:8000/chat/ +# http://10.12.2.2:8000/chat/ execbackend: diff --git a/backend/game/test.js b/backend/game/test.js index d6b38bd9..f6d8fe28 100644 --- a/backend/game/test.js +++ b/backend/game/test.js @@ -1,31 +1,29 @@ // const websocketUrl = 'ws://40.13.7.8:8000/game/asdfasdf/'; -const websocketUrl = 'wss://10.12.2.4/chat/'; - +const websocketUrl = "wss://10.12.2.2/chat/"; // Create a new WebSocket instance const websocket = new WebSocket(websocketUrl); // Event listener for WebSocket connection open -websocket.onopen = function(event) { - console.log('WebSocket connection opened.'); - +websocket.onopen = function (event) { + console.log("WebSocket connection opened."); + // Sending a test message to the server - websocket.send(JSON.stringify({ message: 'Hello from the client!' })); + websocket.send(JSON.stringify({ message: "Hello from the client!" })); }; // Event listener for WebSocket messages received -websocket.onmessage = function(event) { - console.log('Message received from server:', event.data); +websocket.onmessage = function (event) { + console.log("Message received from server:", event.data); // You can add further processing of the received message here }; // Event listener for WebSocket errors -websocket.onerror = function(error) { - console.error('WebSocket error:', error); +websocket.onerror = function (error) { + console.error("WebSocket error:", error); }; // Event listener for WebSocket connection close -websocket.onclose = function(event) { - console.log('WebSocket connection closed.'); +websocket.onclose = function (event) { + console.log("WebSocket connection closed."); }; - diff --git a/docker/backend/backend.sh b/docker/backend/backend.sh index 222e4202..7601eadb 100755 --- a/docker/backend/backend.sh +++ b/docker/backend/backend.sh @@ -25,8 +25,8 @@ echo "alias get='http --follow --timeout 6'" >> /root/.bashrc # ############################################ # mkdir -pv /var/{log,run}/gunicorn/ # gunicorn -c config/gunicorn/dev.py --reload -# sleep 5 -# python manage.py makemigrations && python manage.py migrate +sleep 3 +python manage.py makemigrations && python manage.py migrate # tail -f /var/log/gunicorn/dev.log export DJANGO_SETTINGS_MODULE=backend.settings diff --git a/docker/nginx/config/backend.conf b/docker/nginx/config/backend.conf index c1f49785..f751f1c3 100644 --- a/docker/nginx/config/backend.conf +++ b/docker/nginx/config/backend.conf @@ -6,8 +6,8 @@ server { server_name ${SERVER}; listen 80; listen 443 ssl; - ssl_certificate /etc/ssl/10.12.2.4.crt; - ssl_certificate_key /etc/ssl/10.12.2.4.key; + ssl_certificate /etc/ssl/10.12.2.2.crt; + ssl_certificate_key /etc/ssl/10.12.2.2.key; location / { proxy_pass ${FRONTEND_URL}; diff --git a/docker/nginx/config/nginx.conf b/docker/nginx/config/nginx.conf index 5404c018..f74fa030 100644 --- a/docker/nginx/config/nginx.conf +++ b/docker/nginx/config/nginx.conf @@ -66,18 +66,18 @@ http { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # -# # auth_http 10.12.2.4/auth.php; +# # auth_http 10.12.2.2/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; # # server { -# listen 10.12.2.4:110; +# listen 10.12.2.2:110; # protocol pop3; # proxy on; # } # # server { -# listen 10.12.2.4:143; +# listen 10.12.2.2:143; # protocol imap; # proxy on; # } diff --git a/docker/nginx/nginx.sh b/docker/nginx/nginx.sh index 022888cf..e5949623 100755 --- a/docker/nginx/nginx.sh +++ b/docker/nginx/nginx.sh @@ -12,8 +12,8 @@ sed -i 's|${BACKEND_URL}|'${BACKEND_URL}'|g' /etc/nginx/sites-available/backend sed -i 's|${SERVER}|'${SERVER}'|g' /etc/nginx/sites-available/backend sed -i 's|${LOCATION}|'${LOCATION}'|g' /etc/nginx/sites-available/backend -openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout /etc/ssl/10.12.2.4.key -out /etc/ssl/10.12.2.4.pem -subj "/C=DE/CN=10.12.2.4" -openssl x509 -outform pem -in /etc/ssl/10.12.2.4.pem -out /etc/ssl/10.12.2.4.crt +openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout /etc/ssl/10.12.2.2.key -out /etc/ssl/10.12.2.2.pem -subj "/C=DE/CN=10.12.2.2" +openssl x509 -outform pem -in /etc/ssl/10.12.2.2.pem -out /etc/ssl/10.12.2.2.crt cd /etc/nginx/sites-enabled diff --git a/docker/nginx/nginx_deployment.sh b/docker/nginx/nginx_deployment.sh index 2a2383f8..4499520f 100644 --- a/docker/nginx/nginx_deployment.sh +++ b/docker/nginx/nginx_deployment.sh @@ -6,8 +6,8 @@ sed -i 's|${FRONTEND_URL}|'${FRONTEND_URL}'|g' /etc/nginx/sites-available/backen sed -i 's|${BACKEND_URL}|'${BACKEND_URL}'|g' /etc/nginx/sites-available/backend sed -i 's|${SERVER}|'${SERVER}'|g' /etc/nginx/sites-available/backend -openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout /etc/ssl/10.12.2.4.key -out /etc/ssl/10.12.2.4.pem -subj "/C=DE/CN=10.12.2.4" -openssl x509 -outform pem -in /etc/ssl/10.12.2.4.pem -out /etc/ssl/10.12.2.4.crt +openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout /etc/ssl/10.12.2.2.key -out /etc/ssl/10.12.2.2.pem -subj "/C=DE/CN=10.12.2.2" +openssl x509 -outform pem -in /etc/ssl/10.12.2.2.pem -out /etc/ssl/10.12.2.2.crt cd /etc/nginx/sites-enabled diff --git a/frontend/README.md b/frontend/README.md index 4ca4260e..4e34b5eb 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -9,7 +9,7 @@ In the project directory, you can run: ### `npm start` Runs the app in the development mode.\ -Open [http://10.12.2.4:3000](http://10.12.2.4:3000) to view it in your browser. +Open [http://10.12.2.2:3000](http://10.12.2.2:3000) to view it in your browser. The page will reload when you make changes.\ You may also see any lint errors in the console. diff --git a/frontend/package.json b/frontend/package.json index 3065f52d..14002aaa 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,7 +8,7 @@ "watch:css": "postcss src/styles/tailwind.css -o src/index.css --watch", "start": "REACT_APP_LOCAL_URI=https://10.12.2.2 react-scripts start", "build": "HOMEPAGE=https://zstenger93.github.io/Transcendence/ node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://transcendence-backend-znhl.onrender.com react-scripts build", - "local_build": "node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://10.12.2.4 react-scripts build", + "local_build": "node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://10.12.2.2 react-scripts build", "test": "react-scripts test --detectOpenHandles", "eject": "react-scripts eject" }, @@ -59,4 +59,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/frontend/src/pages/Chat.js b/frontend/src/pages/Chat.js index dec3bcfb..ca06b7b1 100644 --- a/frontend/src/pages/Chat.js +++ b/frontend/src/pages/Chat.js @@ -182,6 +182,25 @@ function Chat({ redirectUri }) { }); }; + const handleInviteMessage = (user) => { + setPrivateMessages((prevMessages) => { + if (!prevMessages.includes(user)) { + if (chatSocket.current.readyState === WebSocket.OPEN) { + chatSocket.current.send( + JSON.stringify({ + message: + "Prove your worthiness to mighty odyn! Beat me in a pong game here: https://10.12.2.2/originalpong", + receiver: user, + }) + ); + } + return [...prevMessages, user]; + } else { + return prevMessages; + } + }); + }; + const openProfile = (user) => { fetchUserProfile(user); }; @@ -292,6 +311,9 @@ function Chat({ redirectUri }) {
  • handleMessageOption(user)}> Message
  • +
  • handleInviteMessage(user)}> + Invitie to play +
  • addFriend({ redirectUri, userName: user }) @@ -360,7 +382,11 @@ function Chat({ redirectUri }) { Profile

    diff --git a/frontend/src/pages/Games/OriginalPong.js b/frontend/src/pages/Games/OriginalPong.js index c5f55d15..37d6f4ef 100644 --- a/frontend/src/pages/Games/OriginalPong.js +++ b/frontend/src/pages/Games/OriginalPong.js @@ -1,4 +1,5 @@ import React, { useEffect, useRef, useState } from "react"; +import Cookies from "js-cookie"; const Pong = () => { const sender = useRef(null); @@ -7,34 +8,42 @@ const Pong = () => { const gameSocket = useRef(null); useEffect(() => { + setTimeout(() => { + const accessToken = Cookies.get("access"); + + if (!accessToken) { + window.location.href = "/404.html"; + } + }, 1000); function randomString(length) { var result = ""; var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); + result += characters.charAt( + Math.floor(Math.random() * charactersLength) + ); } return result; } async function getData() { - let room_name = randomString(10); if (!gameSocket.current) { - gameSocket.current = new WebSocket("wss://10.12.2.4/game/pong/"); + gameSocket.current = new WebSocket("wss://10.12.2.2/game/pong/"); } gameSocket.current.onopen = function (event) { console.log("Data:" + JSON.stringify(receivedData)); console.log("WebSocket is open now.!!!!!!!!!!!!!!!"); }; - gameSocket.current.onclose = function(event) { - console.log('WebSocket is closed now.!!!!!!!!!!!!!!', event.data); + gameSocket.current.onclose = function (event) { + console.log("WebSocket is closed now.!!!!!!!!!!!!!!", event.data); }; - gameSocket.onerror = function(error) { - console.error('WebSocket error:?????????', error); + gameSocket.onerror = function (error) { + console.error("WebSocket error:?????????", error); }; - + let canvas = document.getElementById("gameCanvas"); canvas.width = 1000; canvas.height = 700; @@ -42,14 +51,13 @@ const Pong = () => { let receivedData; gameSocket.current.onmessage = function (event) { receivedData = JSON.parse(event.data); - + if (receivedData["type"] === "game_message") { sender.current = receivedData["sender"]; player0.current = receivedData["users"][0]; player1.current = receivedData["users"][1]; renderGameFrame(receivedData); - } - else if (receivedData["type"] === "ending_message") { + } else if (receivedData["type"] === "ending_message") { console.log("Received Data: " + JSON.stringify(receivedData)); clearCanvas(); displayEndScore(receivedData["game_state"]); @@ -61,7 +69,8 @@ const Pong = () => { if (context && canvas) { clearCanvas(); drawField(); - var score = player0.current + " " + gameData.score + " " + player1.current; + var score = + player0.current + " " + gameData.score + " " + player1.current; displayScore(score); drawPaddle(0, gameData.player0, 10, 110); drawPaddle(1, gameData.player1, 10, 110); @@ -194,7 +203,6 @@ const Pong = () => { }; const handleKeyDown = (event) => { - const user = sender.current; console.log("Key up event: " + user); if (gameSocket.current.readyState === WebSocket.OPEN) { @@ -228,7 +236,6 @@ const Pong = () => { } else { console.log("Socket not open"); } - }; const startGame = () => { @@ -251,7 +258,6 @@ const Pong = () => { } getData(); }, []); - return (

    { id="gameCanvas" width="1000" height="700" - style={{ backgroundColor: "black" , border: "1px solid white" }} + style={{ backgroundColor: "black", border: "1px solid white" }} >
    From 639286748eae1ab2e68c2308c9296c15b2ee881c Mon Sep 17 00:00:00 2001 From: AzerSD Date: Sun, 28 Apr 2024 06:29:29 +0200 Subject: [PATCH 2/6] last minute touches --- backend/backend/settings.py | 43 ++-- backend/backend/urls.py | 2 - backend/game/consumers.py | 34 +-- .../migrations/0003_delete_userchannelname.py | 16 ++ backend/game/models.py | 38 +-- backend/game/urls.py | 8 - backend/game/views.py | 75 ------ backend/user_api/views.py | 236 ++++++++++-------- docker-compose.yaml | 64 ++--- frontend/package.json | 2 +- frontend/src/pages/Games/OriginalPong.js | 175 ++++--------- 11 files changed, 265 insertions(+), 428 deletions(-) create mode 100644 backend/game/migrations/0003_delete_userchannelname.py delete mode 100644 backend/game/urls.py diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 73eaddff..749800f3 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -18,20 +18,20 @@ # SECURITY WARNING: don't run with debug turned on in production! ALLOWED_HOSTS = [ - '*', - 'localhost', - '10.12.2.2', - '172.19.0.4', - '127.0.0.1', - '0.0.0.0', - '10.13.7.5', - 'transcendence-backend-znhl.onrender.com', - 'https://transcendence-frontend-3otz.onrender.com' - ] + "*", + "localhost", + "10.13.1.1", + "172.19.0.4", + "127.0.0.1", + "0.0.0.0", + "10.13.7.5", + "transcendence-backend-znhl.onrender.com", + "https://transcendence-frontend-3otz.onrender.com", +] # Authentication settings -if DEBUG == 'True': - REDIRECT_URI = "https://10.12.2.2" +if DEBUG == "True": + REDIRECT_URI = "https://10.13.1.1" else: REDIRECT_URI = "https://transcendence-backend-znhl.onrender.com" @@ -76,9 +76,8 @@ "whitenoise.middleware.WhiteNoiseMiddleware", ] CSRF_ALLOWED_ORIGINS = [ - - "https://10.12.2.2", - "https://api.intra.42.fr", + "https://10.13.1.1", + "https://api.intra.42.fr", "http://localhost:3000", "http://frontend:3000", "https://transcendence-frontend-3otz.onrender.com", @@ -86,13 +85,13 @@ ] CORS_ALLOWED_ORIGINS = [ - "http://frontend:3000", - "https://api.intra.42.fr", - "https://10.12.2.2", - "http://localhost:3000", - "https://transcendence-frontend-3otz.onrender.com", - "https://zstenger93.github.io" - ] + "http://frontend:3000", + "https://api.intra.42.fr", + "https://10.13.1.1", + "http://localhost:3000", + "https://transcendence-frontend-3otz.onrender.com", + "https://zstenger93.github.io", +] CORS_ALLOW_CREDENTIALS = True # CORS_ORIGIN_ALLOW_ALL = True diff --git a/backend/backend/urls.py b/backend/backend/urls.py index 43f103ee..6378860d 100644 --- a/backend/backend/urls.py +++ b/backend/backend/urls.py @@ -23,7 +23,5 @@ path('admin/', admin.site.urls), path('api/', include('user_api.urls')), path('api/', include('friendship_api.urls')), - # path('api/', include('friendship.urls')), path('chat/', include('chat.urls')), - path('game/', include('game.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/backend/game/consumers.py b/backend/game/consumers.py index cde5c503..2ea8e91f 100644 --- a/backend/game/consumers.py +++ b/backend/game/consumers.py @@ -4,18 +4,7 @@ import math from channels.generic.websocket import AsyncWebsocketConsumer -from channels.db import database_sync_to_async from channels.exceptions import StopConsumer -from rest_framework.request import Request -import secrets -import string - - -## The consumer will be responsible for handling the game logic and updating the game state(websockets) -def generate_random_string(length): - characters = string.ascii_letters + string.digits + "_" - random_string = "".join(secrets.choice(characters) for _ in range(length)) - return random_string import logging @@ -90,7 +79,6 @@ async def receive(self, text_data): cmd = str(game_event[:2]) userid = int(game_event[2:]) # if connected client < 2, then create a new game instance - logger.info(f"connected clientssssssss: {self.connected_clients}") if ( self.room_name not in self.connected_clients and len(self.connected_clients) < 2 @@ -100,12 +88,9 @@ async def receive(self, text_data): self.users[self.room_name][1] = self.scope["user"] self.game_instance = self.connected_clients[self.room_name] - logger.info(f"ccccccconnected clients: {self.connected_clients}") await self.handleInput(cmd, userid) async def handleInput(self, cmd, userid): - logger.info(f"users in room: {self.users[self.room_name]}") - logger.info(f"User {userid} sent command: {cmd}") if cmd == "pw" and userid == self.user_ids[self.room_name][0]: await self.game_instance.move_p0_up("press") elif cmd == "ps" and userid == self.user_ids[self.room_name][0]: @@ -132,12 +117,10 @@ async def disconnect(self, close_code): self.connected_clients = {} # self.game_instance = None self.game_tasks = {} - # self.connected_users = set() await self.channel_layer.group_discard(self.room_group_name, self.channel_name) async def startGame(self): - logger.info(f"Game loop started status: {self.game_state[self.room_name]}") self.game_state[self.room_name] = "starting" await self.send_game_state_to_clients() if self.room_name in self.connected_clients: @@ -165,7 +148,6 @@ async def gameLoop(self): await self.send_game_end() async def send_game_end(self): - game_tag = generate_random_string(20) await self.channel_layer.group_send( self.room_group_name, { @@ -176,7 +158,6 @@ async def send_game_end(self): "room_name": self.room_name, "game_state": self.game_state.get(self.room_name), "users": [str(user) for user in self.users.get(self.room_name)], - "game_tag": game_tag, }, ) @@ -192,7 +173,6 @@ async def ending_message(self, event): "game_state": event["game_state"], "users": event["users"], "user_ids": self.user_ids.get(self.room_name), - "game_tag": event["game_tag"], } ) ) @@ -244,18 +224,6 @@ async def game_message(self, event): ) ) - @database_sync_to_async - def get_room(self, room_name): - from game.models import GameRoom - - return GameRoom.objects.get(name=room_name) - - @database_sync_to_async - def get_all_user_channel_names(self): - from .models import UserChannelName - - return list(UserChannelName.objects.values("user__username")) - class GameInstance: def __init__(self): @@ -280,7 +248,7 @@ def __init__(self): self.p0_moving = 0 self.p1_moving = 0 self.ball_speed = 0 - self.score_to_win = 10 + self.score_to_win = 3 async def move_paddle(self, paddle, direction, state): if state == "press": diff --git a/backend/game/migrations/0003_delete_userchannelname.py b/backend/game/migrations/0003_delete_userchannelname.py new file mode 100644 index 00000000..f2da6eae --- /dev/null +++ b/backend/game/migrations/0003_delete_userchannelname.py @@ -0,0 +1,16 @@ +# Generated by Django 5.0 on 2024-04-28 03:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('game', '0002_remove_gamestats_game_history_remove_gamestats_user_and_more'), + ] + + operations = [ + migrations.DeleteModel( + name='UserChannelName', + ), + ] diff --git a/backend/game/models.py b/backend/game/models.py index 5d9b1696..912f8240 100644 --- a/backend/game/models.py +++ b/backend/game/models.py @@ -1,14 +1,21 @@ - from django.db import models from django.conf import settings -from django.core.serializers import serialize -import json -# Create your models here. + class GameRoom(models.Model): name = models.CharField(max_length=255) - user1 = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="game_user1", null=True) - user2 = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="game_user2", null=True) + user1 = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name="game_user1", + null=True, + ) + user2 = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name="game_user2", + null=True, + ) online = models.ManyToManyField(to=settings.AUTH_USER_MODEL, blank=True) def __str__(self): @@ -18,22 +25,3 @@ class Meta: verbose_name = "Game Room" verbose_name_plural = "Game Rooms" - - -class UserChannelName(models.Model): - AppUser = settings.AUTH_USER_MODEL - user = models.OneToOneField(AppUser, on_delete=models.CASCADE, related_name='game_channel_name') - channel_name = models.CharField(max_length=100) - - def update_channel_name(self, channel_name): - self.channel_name = channel_name - self.save() - - def delete_channel_name(self): - self.delete() - - class Meta: - unique_together = ('user', 'channel_name',) - - def __str__(self): - return self.user.username + ' ' + self.channel_name \ No newline at end of file diff --git a/backend/game/urls.py b/backend/game/urls.py deleted file mode 100644 index 4d48a703..00000000 --- a/backend/game/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.urls import path -from . import views - -app_name = "game" - -urlpatterns = [ - path("ending/", views.end_game, name="end_game"), -] diff --git a/backend/game/views.py b/backend/game/views.py index afdb494c..e69de29b 100644 --- a/backend/game/views.py +++ b/backend/game/views.py @@ -1,75 +0,0 @@ -from .models import * -from django.shortcuts import render, redirect -from django.contrib.auth.decorators import login_required -from .models import * -from user_api.models import AppUser -from django.shortcuts import get_object_or_404 -from django.http.response import JsonResponse -from django.views.decorators.http import require_GET, require_POST -from django.shortcuts import get_object_or_404 -from django.views.decorators.csrf import csrf_exempt -from .consumers import GameConsumer - -from django.contrib.sessions.models import Session -from django.contrib.auth.models import User - -import string -import random -import json -import logging -from django.http import JsonResponse -from channels.layers import get_channel_layer -from asgiref.sync import async_to_sync - - -def get_user_from_session(session_key): - session = Session.objects.get(session_key=session_key) - user_id = session.get_decoded().get("_auth_user_id") - user = User.objects.get(id=user_id) - return user - - -logger = logging.getLogger(__name__) - -# Then, instead of print, use logger.info (or logger.debug, logger.warning, etc.) - - -def generate_random_lobby_name(length=10): - # Generate a random string of the given length - lobby_name = "".join( - random.choice(string.ascii_letters + string.digits) for _ in range(length) - ) - return lobby_name - - -def my_handler(message): - user_id = message.get("user_id") - room_name = message.get("room_name") - print(f"User {user_id} joined room {room_name}") - - -def end_game(request): - lobby_info = request.GET.get("gameinfo", None) - score_board = lobby_info.split(" ") - winner_score = score_board[0] - user1_id = score_board[1] - user2_id = score_board[3] - loser_score = score_board[4] - logger.info(f"Game ended with score: {score_board}") - user1 = get_object_or_404(AppUser, id=user1_id) - user2 = get_object_or_404(AppUser, id=user2_id) - - logger.info(f"Game ended with score: {score_board}") - - return JsonResponse( - { - "winner": user1, - "score": winner_score, - - "loser": user2, - "scoree": loser_score, - } - ) - - -# id1 score1 id2 score2 diff --git a/backend/user_api/views.py b/backend/user_api/views.py index 58078d1d..e4baca95 100644 --- a/backend/user_api/views.py +++ b/backend/user_api/views.py @@ -14,7 +14,6 @@ from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken - from django_otp import devices_for_user from django_otp.plugins.otp_totp.models import TOTPDevice from django.core.mail import EmailMessage @@ -242,81 +241,96 @@ def post(self, request): class OAuthCallback(APIView): - permission_classes = (permissions.AllowAny,) - ## - def get(self, request): - if request.method == "GET": - code = request.GET.get("code") - data = { - "grant_type": "authorization_code", - "client_id": os.environ.get("UID"), - "client_secret": os.environ.get("SECRET"), - "code": code, - "redirect_uri": settings.REDIRECT_URI + "/api/oauth/callback/", - } - auth_response = requests.post("https://api.intra.42.fr/oauth/token", data=data) - - access_token = auth_response.json()["access_token"] - user_response = requests.get("https://api.intra.42.fr/v2/me", headers={"Authorization": f"Bearer {access_token}"}) - - username = user_response.json()["login"] - email = user_response.json()["email"] - - profile_picture_url = user_response.json()["image"]["versions"]["medium"] - response = requests.get(profile_picture_url) - img = Image.open(BytesIO(response.content)) - image_name = os.path.basename(profile_picture_url).lstrip('/') - directory = 'profile_pictures/' - save_path = os.path.join(directory, image_name) - - img_io = BytesIO() - img.save(img_io, format='JPEG') - default_storage.save(save_path, ContentFile(img_io.getvalue())) - - intra_lvl = user_response.json()["cursus_users"][1]["level"] - school = user_response.json()["campus"][0]["name"] - ft_url = user_response.json()["url"], - ft_user = True - - titles = user_response.json().get("titles", []) - title = "" - if titles: - title = titles[0].get("name", "") - title = title.split(" ")[0] - user, created = AppUser.objects.get_or_create( - username = username, - title = title, - intra_level = user_response.json()["cursus_users"][1]["level"], - defaults = { - 'username': username, - 'email': email, - 'title': title, - 'profile_picture': save_path.replace('/app/backend/media', ''), - 'intra_level': intra_lvl, - 'school': school, - 'ft_url': ft_url, - 'ft_user': ft_user - } - ) - login(request, user) - token = RefreshToken.for_user(user) - token['email'] = user.email - token['username'] = user.username - response = Response({ - 'ft_user': user.ft_user, - 'refresh': str(token), - 'access': str(token.access_token), - }, status=status.HTTP_200_OK) - response["Access-Control-Allow-Credentials"] = 'true' - if created or user.TwoFA == False: - redirect_url = 'https://10.12.2.2/home?' + urllib.parse.urlencode({'token': str(token.access_token)}) - else: - redirect_url = 'https://10.12.2.2/2fa?' + urllib.parse.urlencode({'token': str(token.access_token)}) - return redirect(redirect_url) - - response = Response({'detail': "Check you 42API keys"}, status=status.HTTP_400_BAD_REQUEST) - response["Access-Control-Allow-Credentials"] = 'true' - return response + permission_classes = (permissions.AllowAny,) + + ## + def get(self, request): + if request.method == "GET": + code = request.GET.get("code") + data = { + "grant_type": "authorization_code", + "client_id": os.environ.get("UID"), + "client_secret": os.environ.get("SECRET"), + "code": code, + "redirect_uri": settings.REDIRECT_URI + "/api/oauth/callback/", + } + auth_response = requests.post( + "https://api.intra.42.fr/oauth/token", data=data + ) + + access_token = auth_response.json()["access_token"] + user_response = requests.get( + "https://api.intra.42.fr/v2/me", + headers={"Authorization": f"Bearer {access_token}"}, + ) + + username = user_response.json()["login"] + email = user_response.json()["email"] + + profile_picture_url = user_response.json()["image"]["versions"]["medium"] + response = requests.get(profile_picture_url) + img = Image.open(BytesIO(response.content)) + image_name = os.path.basename(profile_picture_url).lstrip("/") + directory = "profile_pictures/" + save_path = os.path.join(directory, image_name) + + img_io = BytesIO() + img.save(img_io, format="JPEG") + default_storage.save(save_path, ContentFile(img_io.getvalue())) + + intra_lvl = user_response.json()["cursus_users"][1]["level"] + school = user_response.json()["campus"][0]["name"] + ft_url = (user_response.json()["url"],) + ft_user = True + + titles = user_response.json().get("titles", []) + title = "" + if titles: + title = titles[0].get("name", "") + title = title.split(" ")[0] + user, created = AppUser.objects.get_or_create( + username=username, + title=title, + intra_level=user_response.json()["cursus_users"][1]["level"], + defaults={ + "username": username, + "email": email, + "title": title, + "profile_picture": save_path.replace("/app/backend/media", ""), + "intra_level": intra_lvl, + "school": school, + "ft_url": ft_url, + "ft_user": ft_user, + }, + ) + login(request, user) + token = RefreshToken.for_user(user) + token["email"] = user.email + token["username"] = user.username + response = Response( + { + "ft_user": user.ft_user, + "refresh": str(token), + "access": str(token.access_token), + }, + status=status.HTTP_200_OK, + ) + response["Access-Control-Allow-Credentials"] = "true" + if created or user.TwoFA == False: + redirect_url = "https://10.13.1.1/home?" + urllib.parse.urlencode( + {"token": str(token.access_token)} + ) + else: + redirect_url = "https://10.13.1.1/2fa?" + urllib.parse.urlencode( + {"token": str(token.access_token)} + ) + return redirect(redirect_url) + + response = Response( + {"detail": "Check you 42API keys"}, status=status.HTTP_400_BAD_REQUEST + ) + response["Access-Control-Allow-Credentials"] = "true" + return response class OAuthAuthorize(APIView): @@ -468,45 +482,63 @@ def post(self, request): class TwoFactorAuth(APIView): - permission_classes = (permissions.IsAuthenticated,) - authentication_classes = (BlacklistCheckJWTAuthentication,) - ## check if use is authenticated - def post(self, request): - otp_code = request.data.get('otp_code') - device = TOTPDevice.objects.filter(user=request.user).first() - - if device and device.verify_token(otp_code): - response = Response({"detail": "OTP verified"}, status=status.HTTP_200_OK) - response["Access-Control-Allow-Credentials"] = 'true' - return response - else: - response = Response({"detail": "Invalid OTP"}, status=status.HTTP_400_BAD_REQUEST) - response["Access-Control-Allow-Credentials"] = 'true' - return response + permission_classes = (permissions.IsAuthenticated,) + authentication_classes = (BlacklistCheckJWTAuthentication,) + + ## check if use is authenticated + def post(self, request): + otp_code = request.data.get("otp_code") + device = TOTPDevice.objects.filter(user=request.user).first() + + if device and device.verify_token(otp_code): + response = Response({"detail": "OTP verified"}, status=status.HTTP_200_OK) + response["Access-Control-Allow-Credentials"] = "true" + return response + else: + response = Response( + {"detail": "Invalid OTP"}, status=status.HTTP_400_BAD_REQUEST + ) + response["Access-Control-Allow-Credentials"] = "true" + return response class UserData(APIView): def get(self, request, username): user = AppUser.objects.get(username=username) if not user: - response = Response({ - "detail": "User not found" - }, status=status.HTTP_404_NOT_FOUND) - response["Access-Control-Allow-Credentials"] = 'true' + response = Response( + {"detail": "User not found"}, status=status.HTTP_404_NOT_FOUND + ) + response["Access-Control-Allow-Credentials"] = "true" return response data = user_to_dict(user) - response = Response({ - "user": data, - }, status=status.HTTP_200_OK) - response["Access-Control-Allow-Credentials"] = 'true' + response = Response( + { + "user": data, + }, + status=status.HTTP_200_OK, + ) + response["Access-Control-Allow-Credentials"] = "true" return response + def user_to_dict(user): user_dict = model_to_dict(user) if user.profile_picture and user.profile_picture.file: - user_dict['profile_picture'] = user.profile_picture.url + user_dict["profile_picture"] = user.profile_picture.url else: - user_dict['profile_picture'] = None + user_dict["profile_picture"] = None # keep only fields : email, username, profile_picture, title, school, intra_level - user_dict = {key: user_dict[key] for key in ['email', 'username', 'profile_picture', 'title', 'school', 'intra_level', 'ft_url']} + user_dict = { + key: user_dict[key] + for key in [ + "email", + "username", + "profile_picture", + "title", + "school", + "intra_level", + "ft_url", + ] + } return user_dict diff --git a/docker-compose.yaml b/docker-compose.yaml index 052f2df0..32ca330e 100755 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -42,38 +42,38 @@ services: - "5432:5432" restart: unless-stopped - prometheus: - image: prom/prometheus - container_name: prometheus - user: "root:root" - ports: - - "9090:9090" - volumes: - - ./docker/prometheus/:/etc/prometheus/ - - ./docker/data/prometheus-data:/prometheus - command: - - '--config.file=/etc/prometheus/prometheus.yml' - - '--storage.tsdb.path=/prometheus/data' - - '--storage.tsdb.retention.time=30d' - restart: unless-stopped - postgres-exporter: - image: wrouesnel/postgres_exporter - container_name: postgres-exporter - environment: - - DATA_SOURCE_NAME=postgresql://transcend_user:transcend_pwd@db:5432/transcend_users_db?sslmode=disable - ports: - - "9187:9187" - restart: unless-stopped - grafana: - image: grafana/grafana-oss:latest - container_name: grafana - user: "root:root" - ports: - - '3200:3200' - volumes: - - ./docker/data/grafana-data:/var/lib/grafana - - ./docker/grafana/provisioning/:/etc/grafana/provisioning/ - - ./docker/grafana/defaults.ini:/etc/grafana/grafana.ini:ro + # prometheus: + # image: prom/prometheus + # container_name: prometheus + # user: "root:root" + # ports: + # - "9090:9090" + # volumes: + # - ./docker/prometheus/:/etc/prometheus/ + # - ./docker/data/prometheus-data:/prometheus + # command: + # - '--config.file=/etc/prometheus/prometheus.yml' + # - '--storage.tsdb.path=/prometheus/data' + # - '--storage.tsdb.retention.time=30d' + # restart: unless-stopped + # postgres-exporter: + # image: wrouesnel/postgres_exporter + # container_name: postgres-exporter + # environment: + # - DATA_SOURCE_NAME=postgresql://transcend_user:transcend_pwd@db:5432/transcend_users_db?sslmode=disable + # ports: + # - "9187:9187" + # restart: unless-stopped + # grafana: + # image: grafana/grafana-oss:latest + # container_name: grafana + # user: "root:root" + # ports: + # - '3200:3200' + # volumes: + # - ./docker/data/grafana-data:/var/lib/grafana + # - ./docker/grafana/provisioning/:/etc/grafana/provisioning/ + # - ./docker/grafana/defaults.ini:/etc/grafana/grafana.ini:ro nginx: container_name: nginx diff --git a/frontend/package.json b/frontend/package.json index 3065f52d..0cdcbff1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,7 @@ "scripts": { "build:css": "postcss src/styles/tailwind.css -o src/index.css", "watch:css": "postcss src/styles/tailwind.css -o src/index.css --watch", - "start": "REACT_APP_LOCAL_URI=https://10.12.2.2 react-scripts start", + "start": "REACT_APP_LOCAL_URI=https://10.13.1.1 react-scripts start", "build": "HOMEPAGE=https://zstenger93.github.io/Transcendence/ node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://transcendence-backend-znhl.onrender.com react-scripts build", "local_build": "node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://10.12.2.4 react-scripts build", "test": "react-scripts test --detectOpenHandles", diff --git a/frontend/src/pages/Games/OriginalPong.js b/frontend/src/pages/Games/OriginalPong.js index c5f55d15..888abb72 100644 --- a/frontend/src/pages/Games/OriginalPong.js +++ b/frontend/src/pages/Games/OriginalPong.js @@ -1,10 +1,10 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef } from "react"; const Pong = () => { const sender = useRef(null); const player0 = useRef(null); const player1 = useRef(null); - const gameSocket = useRef(null); + const game_socket = useRef(null); useEffect(() => { function randomString(length) { @@ -19,19 +19,17 @@ const Pong = () => { } async function getData() { - - let room_name = randomString(10); - if (!gameSocket.current) { - gameSocket.current = new WebSocket("wss://10.12.2.4/game/pong/"); + if (!game_socket.current) { + game_socket.current = new WebSocket("wss://10.13.1.1/game/pong/"); } - gameSocket.current.onopen = function (event) { - console.log("Data:" + JSON.stringify(receivedData)); + game_socket.current.onopen = function (event) { + console.log("Data:" + JSON.stringify(received_data)); console.log("WebSocket is open now.!!!!!!!!!!!!!!!"); }; - gameSocket.current.onclose = function(event) { + game_socket.current.onclose = function(event) { console.log('WebSocket is closed now.!!!!!!!!!!!!!!', event.data); }; - gameSocket.onerror = function(error) { + game_socket.onerror = function(error) { console.error('WebSocket error:?????????', error); }; @@ -39,127 +37,65 @@ const Pong = () => { canvas.width = 1000; canvas.height = 700; let context = canvas.getContext("2d"); - let receivedData; - gameSocket.current.onmessage = function (event) { - receivedData = JSON.parse(event.data); + let received_data; + game_socket.current.onmessage = function (event) { + received_data = JSON.parse(event.data); - if (receivedData["type"] === "game_message") { - sender.current = receivedData["sender"]; - player0.current = receivedData["users"][0]; - player1.current = receivedData["users"][1]; - renderGameFrame(receivedData); + if (received_data["type"] === "game_message") { + sender.current = received_data["sender"]; + player0.current = received_data["users"][0]; + player1.current = received_data["users"][1]; + render_game_frame(received_data); } - else if (receivedData["type"] === "ending_message") { - console.log("Received Data: " + JSON.stringify(receivedData)); - clearCanvas(); - displayEndScore(receivedData["game_state"]); - gameSocket.current.close(); + else if (received_data["type"] === "ending_message") { + console.log("Received Data: " + JSON.stringify(received_data)); + clear_canvas(); + display_end_score(received_data["game_state"]); + game_socket.current.close(); } }; - const renderGameFrame = (gameData) => { + const render_game_frame = (game_data) => { if (context && canvas) { - clearCanvas(); + clear_canvas(); drawField(); - var score = player0.current + " " + gameData.score + " " + player1.current; - displayScore(score); - drawPaddle(0, gameData.player0, 10, 110); - drawPaddle(1, gameData.player1, 10, 110); + var score = player0.current + " " + game_data.score + " " + player1.current; + display_score(score); + draw_paddle(0, game_data.player0, 10, 110); + draw_paddle(1, game_data.player1, 10, 110); drawBall( - gameData.ball_x, - gameData.ball_y, - gameData.ball_speed_x, - gameData.ball_speed_y, - gameData.ball_speed + game_data.ball_x, + game_data.ball_y, ); } }; - const clearCanvas = () => { + const clear_canvas = () => { if (context && canvas) { context.clearRect(0, 0, canvas.width, canvas.height); } }; - function hexToRgb(hex) { - // Remove the hash if it exists - hex = hex.replace(/^#/, ""); - - // Parse the hex values to separate R, G, B components - const bigint = parseInt(hex, 16); - const r = (bigint >> 16) & 255; - const g = (bigint >> 8) & 255; - const b = bigint & 255; - - // Return the RGB values as an object - return { r, g, b }; - } - - const drawBall = (x, y, speedX, speedY, ballSpeed) => { + const drawBall = (x, y) => { if (context) { - // Define a color gradient based on speed - const colorGradient = [ - { speed: 7, color: "#ffff00" }, - { speed: 10, color: "#ff4d00" }, - { speed: 13, color: "#ff0000" }, - { speed: 18, color: "#0000ff" }, - { speed: 50, color: "#bf00ff" }, - ]; - - // Find the color corresponding to the ball's speed in the gradient - let ballColor = "white"; // Default color - for (const { speed, color } of colorGradient) { - if (ballSpeed <= speed) { - ballColor = color; - break; - } - } - - // Display the magnitude of the speed - context.fillStyle = ballColor; - context.font = "14px Arial"; - let show_speed = `Speed: ${ballSpeed.toFixed(3)}`; - context.fillText(show_speed, x - 30, y - 30); + let ballColor = "orange"; - // Draw the main ball context.fillStyle = ballColor; context.beginPath(); - context.arc(x, y, 10, 0, Math.PI * 2); + context.arc(x, y, 11, 0, Math.PI * 2); context.fill(); context.closePath(); - - // Draw the trailing circles - const trailCount = 5; // Adjust the number of circles in the trail - const trailSpacing = 1.5; // Adjust the spacing between circles in the trail - - for (let i = 1; i <= trailCount; i++) { - const trailOpacity = 1 - i / trailCount; - const trailRadius = i * trailSpacing; - - const rgb = hexToRgb(ballColor); - context.fillStyle = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${trailOpacity})`; // Yellow color with variable opacity - context.beginPath(); - context.arc( - x - speedX * trailRadius, - y - speedY * trailRadius, - 10, - 0, - Math.PI * 2 - ); - context.fill(); - context.closePath(); - } } }; - const drawPaddle = (player, y, width, height) => { + const draw_paddle = (player, y, width, height) => { if (context) { if (player === 0) { - context.fillStyle = "red"; // Player 0 Paddle color - context.fillRect(0, y, width, height); + context.fillStyle = "blue"; + context.fillRect(3, y, width, height); } else { - context.fillStyle = "blue"; // Player 1 Paddle color - context.fillRect(990, y, width, height); + context.fillStyle = "red"; + context.fillRect(992, y, width, height); } } }; @@ -171,7 +107,7 @@ const Pong = () => { } }; - const displayScore = (score) => { + const display_score = (score) => { if (context) { context.fillStyle = "white"; context.fillRect(400, 0, 200, 70); @@ -180,7 +116,7 @@ const Pong = () => { context.fillText(score, 450, 50); } }; - const displayEndScore = (score) => { + const display_end_score = (score) => { if (context) { context.fillStyle = "white"; context.fillRect(300, 250, 400, 140); @@ -197,15 +133,11 @@ const Pong = () => { const user = sender.current; console.log("Key up event: " + user); - if (gameSocket.current.readyState === WebSocket.OPEN) { + if (game_socket.current.readyState === WebSocket.OPEN) { if (event.key === "w") { - gameSocket.current.send("pw" + user); + game_socket.current.send("pw" + user); } else if (event.key === "s") { - gameSocket.current.send("ps" + user); - } else if (event.key === "i") { - gameSocket.current.send("pi" + user); - } else if (event.key === "k") { - gameSocket.current.send("pk" + user); + game_socket.current.send("ps" + user); } } else { console.log("Socket not open"); @@ -215,38 +147,26 @@ const Pong = () => { const handleKeyUp = (event) => { const user = sender.current; console.log("Key up event: " + user); - if (gameSocket.current.readyState === WebSocket.OPEN) { + if (game_socket.current.readyState === WebSocket.OPEN) { if (event.key === "w") { - gameSocket.current.send("rw" + user); + game_socket.current.send("rw" + user); } else if (event.key === "s") { - gameSocket.current.send("rs" + user); - } else if (event.key === "i") { - gameSocket.current.send("ri" + user); - } else if (event.key === "k") { - gameSocket.current.send("rk" + user); + game_socket.current.send("rs" + user); } } else { console.log("Socket not open"); } - - }; - - const startGame = () => { - gameSocket.current.send("startgame"); }; document.addEventListener("keyup", handleKeyUp); document.addEventListener("keydown", handleKeyDown); - const startButton = document.getElementById("startGame"); - startButton.addEventListener("click", startGame); // Cleanup function return () => { console.log("closing socket and removing listener"); - gameSocket.current.close(); + game_socket.current.close(); document.removeEventListener("keyup", handleKeyUp); document.removeEventListener("keydown", handleKeyDown); - startButton.removeEventListener("click", startGame); }; } getData(); @@ -270,7 +190,6 @@ const Pong = () => { height="700" style={{ backgroundColor: "black" , border: "1px solid white" }} > - ); }; From d9b7ef704eac3e0a27c05582b0fe179f5b8aee3c Mon Sep 17 00:00:00 2001 From: AzerSD Date: Sun, 28 Apr 2024 06:30:27 +0200 Subject: [PATCH 3/6] updated docker-compose yml --- docker-compose.yaml | 69 +++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 32ca330e..b706fdb9 100755 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -15,6 +15,7 @@ services: # - 4000:4000 restart: unless-stopped command: npm start + backend: container_name: backend env_file: @@ -23,8 +24,8 @@ services: context: . dockerfile: docker/backend/backend.Dockerfile image: transcendence_backend - ports: - - 8000:8000 + # ports: + # - 8000:8000 volumes: - ${PWD}:/app/ entrypoint: /app/docker/backend/backend.sh @@ -42,38 +43,38 @@ services: - "5432:5432" restart: unless-stopped - # prometheus: - # image: prom/prometheus - # container_name: prometheus - # user: "root:root" - # ports: - # - "9090:9090" - # volumes: - # - ./docker/prometheus/:/etc/prometheus/ - # - ./docker/data/prometheus-data:/prometheus - # command: - # - '--config.file=/etc/prometheus/prometheus.yml' - # - '--storage.tsdb.path=/prometheus/data' - # - '--storage.tsdb.retention.time=30d' - # restart: unless-stopped - # postgres-exporter: - # image: wrouesnel/postgres_exporter - # container_name: postgres-exporter - # environment: - # - DATA_SOURCE_NAME=postgresql://transcend_user:transcend_pwd@db:5432/transcend_users_db?sslmode=disable - # ports: - # - "9187:9187" - # restart: unless-stopped - # grafana: - # image: grafana/grafana-oss:latest - # container_name: grafana - # user: "root:root" - # ports: - # - '3200:3200' - # volumes: - # - ./docker/data/grafana-data:/var/lib/grafana - # - ./docker/grafana/provisioning/:/etc/grafana/provisioning/ - # - ./docker/grafana/defaults.ini:/etc/grafana/grafana.ini:ro + prometheus: + image: prom/prometheus + container_name: prometheus + user: "root:root" + ports: + - "9090:9090" + volumes: + - ./docker/prometheus/:/etc/prometheus/ + - ./docker/data/prometheus-data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus/data' + - '--storage.tsdb.retention.time=30d' + restart: unless-stopped + postgres-exporter: + image: wrouesnel/postgres_exporter + container_name: postgres-exporter + environment: + - DATA_SOURCE_NAME=postgresql://transcend_user:transcend_pwd@db:5432/transcend_users_db?sslmode=disable + ports: + - "9187:9187" + restart: unless-stopped + grafana: + image: grafana/grafana-oss:latest + container_name: grafana + user: "root:root" + ports: + - '3200:3200' + volumes: + - ./docker/data/grafana-data:/var/lib/grafana + - ./docker/grafana/provisioning/:/etc/grafana/provisioning/ + - ./docker/grafana/defaults.ini:/etc/grafana/grafana.ini:ro nginx: container_name: nginx From 6e55d27d6b28756f57f160fbe520efb5c0741d2d Mon Sep 17 00:00:00 2001 From: AzerSD Date: Sun, 28 Apr 2024 06:59:26 +0200 Subject: [PATCH 4/6] fixed 2fa --- backend/qrcode.png | Bin 0 -> 1089 bytes backend/user_api/views.py | 29 ++++++++--------------------- 2 files changed, 8 insertions(+), 21 deletions(-) create mode 100644 backend/qrcode.png diff --git a/backend/qrcode.png b/backend/qrcode.png new file mode 100644 index 0000000000000000000000000000000000000000..0ffab38c94c1197aeef064dfc9807e82d3f98193 GIT binary patch literal 1089 zcmV-H1it%;P) zL2l$Y3`IZN25PCgK^?`uK_4loo7qRn0S2&_1=#q#kSM7#J6nTH+Mf#}it9lsfS|-r zN-^Su&A-mjfN(~JLncHx)81IY=1je)cgy8&SX zhR;4aT+B5_03^4@vkSi@KATw#X;^yz>y7sDdGpnE?Q^W#J)3PfyYP$QabH);VvIYt z@Urv(5ThQj8|#lYm|gfaaaT^FXo4t}0La5AsrZW_swth66X6Z;@Upa}^Bo@MJ76Pr zvoUNidu-s-`jlKWon82~@D%F+c=`$;D#8d`9F{PbG7N4h2rAYIKaRVvZLkme9&SQM z`&a-Q(GghtxVZ9p?`UJY*@a&X_n;L>0C~R_axn~@*T%|=Y>IWlkK;CCH%{SYd`4NM zquGPRz?WgR8!_K^Pie7BIT3!wJcmWD^ye&f$zjfi@lnOZAN}2he>>jM#;^fcZ*;wG zi!U%gT)CSc8)8hHn$9l#iuim7QVD_^;*y%G6g`k#kNiwS8yn6p{9?E(C&5#N30)dy zZP-`XlYC;W^RMWj}Lvp_N-SINQ_yNbQjSY9Xm zsCjLoW08t|_*R>Z5w2vj@;c#1E%g!)({32J_l!Ag?63RBVy$c*;R#3E*@a&jPdP*s zO}3oU-iY~;s$|~FS)}4-vkSi({=TncTvsvVQ(*5JvY#b`s{g{znEO?#Ie17b+qd^L zqv$H~I^k#W@G_Dw!+dv@?wKnRSbLs+8q4RxhJ`vp_16MoD} z+fr3{Ee)Ny(7 z)ZbJeo>(%Y6;}8;g zHT++9b*2P$tAbnkh(EN#3U7h0`KsadMjQQPL^`OrnsHitztb*$q~YwsFOCn(9zBd) z06+U*j?9u;VTCuwEr+>yiOziY" ) to_email = request.user.email email = EmailMessage(mail_subject, message, to=[to_email]) + # Attach image fp = open("qrcode.png", "rb") msg_image = MIMEImage(fp.read()) fp.close() - msg_image = MIMEImage(byte_stream.getvalue()) msg_image.add_header("Content-ID", "") email.attach(msg_image) @@ -461,24 +458,18 @@ def post(self, request): messages.success( request, ("Please Confirm your email to complete registration.") ) - response = Response( + return Response( {"detail": "QR Code sent to your email"}, status=status.HTTP_200_OK ) - response["Access-Control-Allow-Credentials"] = "true" - return response else: - response = Response( + return Response( {"detail": "Two Factor Authentication is not activated"}, status=status.HTTP_400_BAD_REQUEST, ) - response["Access-Control-Allow-Credentials"] = "true" - return response else: - response = Response( + return Response( {"detail": "No active user session"}, status=status.HTTP_400_BAD_REQUEST ) - response["Access-Control-Allow-Credentials"] = "true" - return response class TwoFactorAuth(APIView): @@ -491,15 +482,11 @@ def post(self, request): device = TOTPDevice.objects.filter(user=request.user).first() if device and device.verify_token(otp_code): - response = Response({"detail": "OTP verified"}, status=status.HTTP_200_OK) - response["Access-Control-Allow-Credentials"] = "true" - return response + return Response({"detail": "OTP verified"}, status=status.HTTP_200_OK) else: - response = Response( + return Response( {"detail": "Invalid OTP"}, status=status.HTTP_400_BAD_REQUEST ) - response["Access-Control-Allow-Credentials"] = "true" - return response class UserData(APIView): From 640c10596987969f20ab3ca2770cc7e0cdefc951 Mon Sep 17 00:00:00 2001 From: Zsolt Stenger Date: Sun, 28 Apr 2024 07:27:00 +0200 Subject: [PATCH 5/6] fixed game score --- backend/backend/settings.py | 8 +++--- backend/game/consumers.py | 7 +++-- backend/user_api/views.py | 4 +-- frontend/package.json | 4 +-- frontend/src/pages/Games/OriginalPong.js | 35 ++++++++++++------------ 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 749800f3..9070a647 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -20,7 +20,7 @@ ALLOWED_HOSTS = [ "*", "localhost", - "10.13.1.1", + "10.12.2.2", "172.19.0.4", "127.0.0.1", "0.0.0.0", @@ -31,7 +31,7 @@ # Authentication settings if DEBUG == "True": - REDIRECT_URI = "https://10.13.1.1" + REDIRECT_URI = "https://10.12.2.2" else: REDIRECT_URI = "https://transcendence-backend-znhl.onrender.com" @@ -76,7 +76,7 @@ "whitenoise.middleware.WhiteNoiseMiddleware", ] CSRF_ALLOWED_ORIGINS = [ - "https://10.13.1.1", + "https://10.12.2.2", "https://api.intra.42.fr", "http://localhost:3000", "http://frontend:3000", @@ -87,7 +87,7 @@ CORS_ALLOWED_ORIGINS = [ "http://frontend:3000", "https://api.intra.42.fr", - "https://10.13.1.1", + "https://10.12.2.2", "http://localhost:3000", "https://transcendence-frontend-3otz.onrender.com", "https://zstenger93.github.io", diff --git a/backend/game/consumers.py b/backend/game/consumers.py index 2ea8e91f..1bf63e91 100644 --- a/backend/game/consumers.py +++ b/backend/game/consumers.py @@ -115,8 +115,9 @@ async def disconnect(self, close_code): if not self.connected_users: self.game_state = {} self.connected_clients = {} - # self.game_instance = None + self.game_instance = None self.game_tasks = {} + self.connected_users = set() await self.channel_layer.group_discard(self.room_group_name, self.channel_name) @@ -248,7 +249,7 @@ def __init__(self): self.p0_moving = 0 self.p1_moving = 0 self.ball_speed = 0 - self.score_to_win = 3 + self.score_to_win = 10 async def move_paddle(self, paddle, direction, state): if state == "press": @@ -288,7 +289,7 @@ async def update_game(self, game_state, room_name, user0, user1): 0, min(self.canvas_height - self.paddle_height, self.player1) ) await self.update_ball_position(game_state, room_name, user0, user1) - self.score = f"{self.player0_score} : {self.player1_score}" + self.score = f"{self.player1_score} : {self.player0_score}" self.ball_speed = math.sqrt(self.ball_speed_x**2 + self.ball_speed_y**2) async def update_ball_position(self, game_state, room_name, user0, user1): diff --git a/backend/user_api/views.py b/backend/user_api/views.py index e4baca95..9c5114d2 100644 --- a/backend/user_api/views.py +++ b/backend/user_api/views.py @@ -317,11 +317,11 @@ def get(self, request): ) response["Access-Control-Allow-Credentials"] = "true" if created or user.TwoFA == False: - redirect_url = "https://10.13.1.1/home?" + urllib.parse.urlencode( + redirect_url = "https://10.12.2.2/home?" + urllib.parse.urlencode( {"token": str(token.access_token)} ) else: - redirect_url = "https://10.13.1.1/2fa?" + urllib.parse.urlencode( + redirect_url = "https://10.12.2.2/2fa?" + urllib.parse.urlencode( {"token": str(token.access_token)} ) return redirect(redirect_url) diff --git a/frontend/package.json b/frontend/package.json index 937c9e1f..c93f0fe3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,7 @@ "scripts": { "build:css": "postcss src/styles/tailwind.css -o src/index.css", "watch:css": "postcss src/styles/tailwind.css -o src/index.css --watch", - "start": "REACT_APP_LOCAL_URI=https://10.13.1.1 react-scripts start", + "start": "REACT_APP_LOCAL_URI=https://10.12.2.2 react-scripts start", "build": "HOMEPAGE=https://zstenger93.github.io/Transcendence/ node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://transcendence-backend-znhl.onrender.com react-scripts build", "local_build": "node SetHomepage.js && CI=false NODE_ENV=production REACT_APP_REDIRECT_URI=https://10.12.2.2 react-scripts build", "test": "react-scripts test --detectOpenHandles", @@ -59,4 +59,4 @@ "last 1 safari version" ] } -} \ No newline at end of file +} diff --git a/frontend/src/pages/Games/OriginalPong.js b/frontend/src/pages/Games/OriginalPong.js index befe14f2..3bf06049 100644 --- a/frontend/src/pages/Games/OriginalPong.js +++ b/frontend/src/pages/Games/OriginalPong.js @@ -30,17 +30,17 @@ const Pong = () => { async function getData() { if (!game_socket.current) { - game_socket.current = new WebSocket("wss://10.13.1.1/game/pong/"); + game_socket.current = new WebSocket("wss://10.12.2.2/game/pong/"); } game_socket.current.onopen = function (event) { console.log("Data:" + JSON.stringify(received_data)); console.log("WebSocket is open now.!!!!!!!!!!!!!!!"); }; - game_socket.current.onclose = function(event) { - console.log('WebSocket is closed now.!!!!!!!!!!!!!!', event.data); + game_socket.current.onclose = function (event) { + console.log("WebSocket is closed now.!!!!!!!!!!!!!!", event.data); }; - game_socket.onerror = function(error) { - console.error('WebSocket error:?????????', error); + game_socket.onerror = function (error) { + console.error("WebSocket error:?????????", error); }; let canvas = document.getElementById("gameCanvas"); @@ -50,14 +50,13 @@ const Pong = () => { let received_data; game_socket.current.onmessage = function (event) { received_data = JSON.parse(event.data); - + if (received_data["type"] === "game_message") { sender.current = received_data["sender"]; player0.current = received_data["users"][0]; player1.current = received_data["users"][1]; render_game_frame(received_data); - } - else if (received_data["type"] === "ending_message") { + } else if (received_data["type"] === "ending_message") { console.log("Received Data: " + JSON.stringify(received_data)); clear_canvas(); display_end_score(received_data["game_state"]); @@ -69,14 +68,12 @@ const Pong = () => { if (context && canvas) { clear_canvas(); drawField(); - var score = player0.current + " " + game_data.score + " " + player1.current; + var score = + player0.current + " " + game_data.score + " " + player1.current; display_score(score); draw_paddle(0, game_data.player0, 10, 110); draw_paddle(1, game_data.player1, 10, 110); - drawBall( - game_data.ball_x, - game_data.ball_y, - ); + drawBall(game_data.ball_x, game_data.ball_y); } }; @@ -119,13 +116,15 @@ const Pong = () => { const display_score = (score) => { if (context) { - context.fillStyle = "white"; - context.fillRect(400, 0, 200, 70); - context.fillStyle = "black"; - context.fillText("Score", 400, 50); - context.fillText(score, 450, 50); + context.fillStyle = "white"; + context.textAlign = "center"; + context.textBaseline = "middle"; + context.font = "bold 24px Arial"; + context.fillText(score, canvas.width / 2, canvas.height / 2); } }; + + const display_end_score = (score) => { if (context) { context.fillStyle = "white"; From 72c0d8a18a8e44ae658bf55b55631bb2a61e2a28 Mon Sep 17 00:00:00 2001 From: Zsolt Stenger Date: Sun, 28 Apr 2024 07:38:06 +0200 Subject: [PATCH 6/6] qr fix --- .gitignore | 2 ++ backend/qrcode.png | Bin 1089 -> 1324 bytes 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 4654ac84..196d13f1 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ backend/authentication/images/* media node_modules +backend/qrcode* + #ssl_keys *.crt *.key diff --git a/backend/qrcode.png b/backend/qrcode.png index 0ffab38c94c1197aeef064dfc9807e82d3f98193..58f16a369203e1ccff1e0efc9a598a8cc1fd97b2 100644 GIT binary patch literal 1324 zcmV+{1=IS8P) zUy9^55XQfX4f80&9$=1Q-ylZ{eWcvLI?5a%U_CC_R320%$-R?oV0(mPK0O$>+x}re zQL4YPD1LRs-+mbZkU<6+WRO7y8Dx+_MrDYN5wawad~Hc0h|?j6A_624S^SSYmKVPV z8D#v!P*qjTs;asTn#WrHo>did{$mGb-BIt$kF8gk3mNxkq@o?u2w5;F5L6Lmgs$Pc z0BLNV6Or+m@rw5#gN*;ekOhbMk3%r)4j{d$$TX-vCP0=B??DC`|H_E(sz4UjK@mkn zWI6=%20SU%uY3WA6BD8ia?Nc)PGE8j(m_JNo${!zZS{0}) z=}j?zjF1IKcK2WZ9%PX5>Bv&pCQri-Abc0ZX|SJhf@qu|3hdDH{nwcb8Fy#M0uPu1 zhv;L1dHFeX8f?jzW=zGSy4GCCxGzH=(;?Y3wS|6ATla&i*#b$#f~XsyE9`K!xsY*3 zhWSzXtcLUb%nsY2CY@mifI;iC^rOi5dWOl`d0^fKcjm(mU4yEw@M|_K8bCQES@#D8!j78Sw}2@C)eUIY{T%TRJJ)?OdNEv1gDcg> zNX>zLGgnm5&#%>L7F^_dX>45 zaeGG0rKc8>vVdtS87BbxcrOW6ps^1wHy1K)$SD4Pu{MLcrCJXji1Kv5%PH4=GWsy` zx^H?jP5Fn$-vOC7D3IQ)d}{u4f&#|~VAz4M`D0g^3mLa(%o`w!7emRCM(Cqfn!r|j z#0fxSuD<#`$ROkM;r_mhp84^`-v{6^s1lOO_c1O-MmL7bnkSpGB+i~owKLC_)+|)} z>{aGM#{C(k11i4n(8mP0({C{VT~P|8(uj8PzuH{LxGiJOwNXVdlZYixvpAMcsS>rS z7Qof!LdFdlr@UzyZIT~mi>^=JQ(!)djBbpkKdNz|Y@v5AzeM+I#dHq#(>^7m52K0h zdmo<{oSMe;{C-aDpA!F+Q!+X+N?l*O6^a*}TB%f~ z%!Q2mGF+c-K;tuI`SUQTs+L0ka7tNGPRZ!QD0x$FF9C*=dOe>N0d6;;yvkh2xG&?h zztpMvq?)TwXD2g&a!N)IM&n1F5~a0lza*tLKh$79^(h&B7}g&Z7XS#~MXfLz05I$_ zZ<8p}w;jMfYJ67!X@tf_*dIkkFGgASceEvap=MCw+oNpN7VyD!pNu|?=lxKgLQ=K< z)LpH%PL=CE8C@Cmdnb9jv$b^X*KN@jlwHxiPW9#QK?WJ0kJ7&n0O?!a+*Ia|5rVLx z$xH#qs7SDD^ICR6y~&mUs@pXRd(ux)##d}8Y5??DC`pN;3wLTH=@ zDAFN{H0)xE7DdPYh3x*vX`{bSMlZ&XpD(F>`GCvhg4`0F8~cF)0*r2;US%$1+?Vm` z_xS9uQ?GQ5_?wr{I6oQv7-$8v)IT>>QsrwrHCtNlWBiniP7KkX-}93ZuQC@h$RL9Z iGRPo<3^M-zjK2ZhL8y&|3v1K>0000 zL2l$Y3`IZN25PCgK^?`uK_4loo7qRn0S2&_1=#q#kSM7#J6nTH+Mf#}it9lsfS|-r zN-^Su&A-mjfN(~JLncHx)81IY=1je)cgy8&SX zhR;4aT+B5_03^4@vkSi@KATw#X;^yz>y7sDdGpnE?Q^W#J)3PfyYP$QabH);VvIYt z@Urv(5ThQj8|#lYm|gfaaaT^FXo4t}0La5AsrZW_swth66X6Z;@Upa}^Bo@MJ76Pr zvoUNidu-s-`jlKWon82~@D%F+c=`$;D#8d`9F{PbG7N4h2rAYIKaRVvZLkme9&SQM z`&a-Q(GghtxVZ9p?`UJY*@a&X_n;L>0C~R_axn~@*T%|=Y>IWlkK;CCH%{SYd`4NM zquGPRz?WgR8!_K^Pie7BIT3!wJcmWD^ye&f$zjfi@lnOZAN}2he>>jM#;^fcZ*;wG zi!U%gT)CSc8)8hHn$9l#iuim7QVD_^;*y%G6g`k#kNiwS8yn6p{9?E(C&5#N30)dy zZP-`XlYC;W^RMWj}Lvp_N-SINQ_yNbQjSY9Xm zsCjLoW08t|_*R>Z5w2vj@;c#1E%g!)({32J_l!Ag?63RBVy$c*;R#3E*@a&jPdP*s zO}3oU-iY~;s$|~FS)}4-vkSi({=TncTvsvVQ(*5JvY#b`s{g{znEO?#Ie17b+qd^L zqv$H~I^k#W@G_Dw!+dv@?wKnRSbLs+8q4RxhJ`vp_16MoD} z+fr3{Ee)Ny(7 z)ZbJeo>(%Y6;}8;g zHT++9b*2P$tAbnkh(EN#3U7h0`KsadMjQQPL^`OrnsHitztb*$q~YwsFOCn(9zBd) z06+U*j?9u;VTCuwEr+>yiOziY