diff --git a/src/components/views/Gameroom.tsx b/src/components/views/Gameroom.tsx index 0224147..a11cc84 100644 --- a/src/components/views/Gameroom.tsx +++ b/src/components/views/Gameroom.tsx @@ -167,6 +167,16 @@ const Gameroom = () => { // console.log(mssg) console.log("[onResponseReceived] receiptId",msg.receiptId) console.log("[onResponseReceived] reqList:",requestLists.current) + + // Check if the message indicates an invalid or expired token + if (msg.auth === false) { + showToast("Invalid or expired token, please login again!", "error"); + sessionStorage.clear(); // Clear session storage + navigate("/login"); // Navigate to the login page + + return; // Exit the function to avoid further processing + } + const index = requestLists.current.findIndex(item => item.receiptId === msg.receiptId); if (index !== INDEX_NOT_FOUND) { const messageType = requestLists.current[index].type; @@ -214,6 +224,7 @@ const Gameroom = () => { /// 2. if the response is success, do nothing /// 3. if the response is failure, show the error message /// 4. if the response is not received, do something to handle the timeout + /// 5. if the response is unauthorized, navigate to login page and clear session }; const onPlayerInfoReceived = (payload) => { @@ -396,7 +407,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current?.send( `/app/message/users/enterroom/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); requestLists.current.push({ type: "enter",receiptId: receiptId }); @@ -429,7 +441,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current?.send( `/app/message/users/ready/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); requestLists.current.push({ type: "ready",receiptId: receiptId }); @@ -461,7 +474,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current?.send( `/app/message/users/unready/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); requestLists.current.push({ type: "unready",receiptId: receiptId }); @@ -493,7 +507,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current?.send( `/app/message/games/start/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); requestLists.current.push({ type: "start",receiptId: receiptId }); @@ -527,7 +542,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current?.send( `/app/message/users/exitroom/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); // requestLists.current.push({ type: "leave",receiptId: receiptId }); @@ -562,7 +578,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current?.send( `/app/message/games/validate/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); requestLists.current.push({ type: "submit",receiptId: receiptId }); @@ -603,7 +620,8 @@ const Gameroom = () => { const receiptId = uuidv4(); stompClientRef.current.send( `/app/message/games/audio/upload/${currentRoomID}`, - { receiptId: receiptId }, + { receiptId: receiptId, + token: sessionStorage.getItem("token") }, JSON.stringify(payload) ); requestLists.current.push({ type: "upload",receiptId: receiptId }); diff --git a/src/components/views/Lobby.tsx b/src/components/views/Lobby.tsx index 8a8d93a..a843e8b 100644 --- a/src/components/views/Lobby.tsx +++ b/src/components/views/Lobby.tsx @@ -1,5 +1,4 @@ import React, { useCallback, useRef, useEffect, useState } from "react"; -import { v4 as uuidv4 } from "uuid"; import { api, handleError } from "helpers/api"; import { Button } from "components/ui/Button"; import { throttle } from "lodash"; @@ -12,7 +11,7 @@ import { Dropdown } from "components/ui/Dropdown"; import "styles/views/Lobby.scss"; import { getDomain } from "helpers/getDomain"; import "styles/ui/Popup.scss"; -import { MAX_USERNAME_LENGTH, MAX_ROOM_NAME_LENGTH } from "../../constants/constants"; +import { MAX_USERNAME_LENGTH, MAX_ROOM_NAME_LENGTH, HTTP_STATUS } from "../../constants/constants"; import SockJS from "sockjs-client"; import { over } from "stompjs"; import { showToast} from "../../helpers/toastService"; @@ -119,7 +118,6 @@ const Lobby = () => { const logout = async () => { const id = sessionStorage.getItem("id"); - sessionStorage.removeItem("token"); //apply a post request for user logout try { const requestBody = JSON.stringify({ id: id }); @@ -187,7 +185,7 @@ const Lobby = () => { // showToast("Reconnect to your previous room!", "success"); // } - setRooms(payload); // 确保这里是数组 + setRooms(payload); console.log("Rooms updated:", message_lobby.message); } else { console.error("Received data is not in expected format:", message_lobby); @@ -287,7 +285,7 @@ const Lobby = () => { console.log("Room ID:", response.data.roomId); const roomId = response.data.roomId; navigate(`/rooms/${roomId}/${roomName}`); - //toggleRoomCreationPop(); // 关闭创建房间的弹窗 + //toggleRoomCreationPop(); } catch (error) { handleError(error); @@ -386,13 +384,30 @@ const Lobby = () => { /// /// if error is network error, clear the session and navigate to login page + /// if unauthorized, clear the session and navigate to login page /// const handleError = (error) => { - // if(!error.message){ - // // if error message is undefined - // showToast("Something went wrong, please try again later.", "error"); - // } - if (error.message.match(/Network Error/)) { + // Check if there's a response object in the error + if (error.response) { + const { status, data } = error.response; + + // Handle 401 Unauthorized errors + if (status === HTTP_STATUS.UNAUTHORIZED) { + console.error("Unauthorized: " + data.message + "\n" + error); + showToast("Your session has expired or is invalid. Please log in again.", "error"); + sessionStorage.clear(); + navigate("/login"); + } else if (status === HTTP_STATUS.FORBIDDEN) { + // Handle 403 Forbidden errors + console.error("Forbidden: Access is denied. " + data.message + "\n" + error); + showToast("Access is denied. You do not have permission to access this resource.", "error"); + } else { + // Handle other types of errors generically + console.error(`Error: ${data.message}\n${error}`); + showToast("An error occurred: ${data.message}", "error"); + } + } else if (error.message && error.message.match(/Network Error/)) { + // Handle network errors console.error(`The server cannot be reached.\nDid you start it?\n${error}`); showToast(`The server cannot be reached.\nDid you start it?\n${error}`); sessionStorage.clear(); @@ -400,12 +415,22 @@ const Lobby = () => { showToast("The server cannot be reached.\nDid you start it?", "error"); } else { console.error(`Something went wrong: \n${error}`); - showToast(`Something went wrong: \n${error}`); + showToast("Something went wrong: \n${error}", "error"); } } const throttledClickHandler = throttle((Room, navigate, showToast) => { try { + // Check if the session token is empty + const token = sessionStorage.getItem("token"); + if (!token) { + showToast("Session expired or invalid, please log in again.", "error"); + sessionStorage.clear(); // Clear session storage + navigate("/login"); + + return; // Exit the function to avoid further processing + } + if (Room.roomPlayersList.length === Room.roomMaxNum) { showToast("Room is Full, please enter another room!", "error"); } else if (Room.status === "In Game") { diff --git a/src/helpers/api.js b/src/helpers/api.js index a027f6b..298dfef 100644 --- a/src/helpers/api.js +++ b/src/helpers/api.js @@ -1,11 +1,30 @@ import axios from "axios"; import { getDomain } from "./getDomain"; +import {HTTP_STATUS} from "../constants/constants" export const api = axios.create({ baseURL: getDomain(), headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" } }); +// Request interceptor +api.interceptors.request.use(function (config) { + const token = sessionStorage.getItem("token"); + if (token) { + config.headers.Authorization = `Bearer ${token}`; // Append token to headers if it exists + } + console.log("Sending request to:", config.url); + console.log("Request headers:", config.headers); + console.log("Request method:", config.method); + if (config.data) { + console.log("Request data:", config.data); + } + + return config; +}, function (error) { + return Promise.reject(error); // Handle request error +}); + export const handleError = error => { const response = error.response;