diff --git a/leaky-ships/components/Gamefield/Gamefield.tsx b/leaky-ships/components/Gamefield/Gamefield.tsx index 0a34c0c..39ab1de 100644 --- a/leaky-ships/components/Gamefield/Gamefield.tsx +++ b/leaky-ships/components/Gamefield/Gamefield.tsx @@ -1,24 +1,20 @@ // import Bluetooth from './Bluetooth' -import BorderTiles from "./BorderTiles" -import EventBar from "./EventBar" // import FogImages from './FogImages' -import HitElems from "./HitElems" import Labeling from "./Labeling" import Ships from "./Ships" -import Targets from "./Targets" import useGameEvent from "@lib/hooks/useGameEvent" import { CSSProperties } from "react" function Gamefield() { const count = 12 - const { pointersProps, targetsProps, tilesProps, hits } = useGameEvent(count) + const { BorderTiles, HitElems, Targets, EventBar } = useGameEvent(count) return (
{/* */}
{/* Bordes */} - + {/* Collumn lettes and row numbers */} @@ -26,14 +22,14 @@ function Gamefield() { {/* Ships */} - + {/* Fog images */} {/* */} - + {/* Debug */}
- +
) } diff --git a/leaky-ships/components/Lobby/LobbyFrame.tsx b/leaky-ships/components/Lobby/LobbyFrame.tsx index 2026426..bc71f1d 100644 --- a/leaky-ships/components/Lobby/LobbyFrame.tsx +++ b/leaky-ships/components/Lobby/LobbyFrame.tsx @@ -1,8 +1,10 @@ +import { gameContext } from "../../pages/_app" import Icon from "./Icon" import Player from "./Player" -import { Fragment, useEffect, useState } from "react" +import { Fragment, useContext, useEffect, useState } from "react" function LobbyFrame({ openSettings }: { openSettings: () => void }) { + const [gameProps, setGameProps] = useContext(gameContext) const [enemy, setEnemy] = useState(false) const [dots, setDots] = useState(1) @@ -17,7 +19,7 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
Chat

- Game-PIN: 3169 + Game-PIN: {gameProps.pin}

Settings diff --git a/leaky-ships/lib/backend/components/decodeToken.ts b/leaky-ships/lib/backend/components/decodeToken.ts new file mode 100644 index 0000000..357c8d5 --- /dev/null +++ b/leaky-ships/lib/backend/components/decodeToken.ts @@ -0,0 +1,35 @@ +import { rejectionErrorFns } from "../errors" +import jwtVerifyCatch from "../jwtVerifyCatch" +import logging from "../logging" +import type { IdToken, RawToken } from "./createTokenDB" +import sendError, { API } from "./sendError" +import jwt from "jsonwebtoken" + +async function decodeToken( + context: API, + rawToken: RawToken, + next: (token: IdToken) => void +) { + const { value, type } = rawToken + + // Verify the token and get the payload + let data: string | jwt.JwtPayload + try { + data = jwt.verify(value, process.env.TOKEN_SECRET as string) + } catch (err: any) { + // Deal with the problem in more detail + logging(jwtVerifyCatch(type, err).message, ["error"]) + const fallbackData = jwt.decode(value) + // Making sure the token data is not a string (because it should be an object) + if (typeof fallbackData === "string") + return sendError(context, rejectionErrorFns.tokenWasString(type, value)) + return next({ id: fallbackData?.id, type }) + } + // Making sure the token data is not a string (because it should be an object) + if (typeof data === "string") + return sendError(context, rejectionErrorFns.tokenWasString(type, value)) + + return next({ id: data.id, type }) +} + +export default decodeToken diff --git a/leaky-ships/lib/backend/components/getTokenDB.ts b/leaky-ships/lib/backend/components/getTokenDB.ts index 7263677..17e4fc2 100644 --- a/leaky-ships/lib/backend/components/getTokenDB.ts +++ b/leaky-ships/lib/backend/components/getTokenDB.ts @@ -7,7 +7,8 @@ import type { Token } from "@prisma/client" async function getTokenDB( context: API, token: IdToken, - next: (tokenDB: Token) => void + next: (tokenDB: Token) => void, + ignoreChecks?: boolean ) { const { id, type } = token // Find refresh token in DB @@ -18,14 +19,15 @@ async function getTokenDB( }) if (!tokenDB) return sendError(context, rejectionErrorFns.tokenNotFound(type)) - if (tokenDB.used) return sendError(context, rejectionErrors.tokenUsed) + if (tokenDB.used && !ignoreChecks) + return sendError(context, rejectionErrors.tokenUsed) await prisma.token.update({ where: { id, }, data: { - used: true, + used: type === "ACCESS", }, }) diff --git a/leaky-ships/lib/backend/components/getTokenFromCookie.ts b/leaky-ships/lib/backend/components/getTokenFromCookie.ts index 62c7337..9ccbe45 100644 --- a/leaky-ships/lib/backend/components/getTokenFromCookie.ts +++ b/leaky-ships/lib/backend/components/getTokenFromCookie.ts @@ -1,18 +1,32 @@ import createPlayerDB from "./createPlayerDB" import createTokenDB, { RawToken } from "./createTokenDB" import type { API } from "./sendError" +import { setCookie } from "cookies-next" async function getTokenFromCookie( context: API, next: (refreshToken: RawToken) => void ) { const type = "REFRESH" - const value = context.req.cookies.token + const { req, res } = context + const value = req.cookies.token // Checking for cookie presens, because it is necessary if (!value) { return createPlayerDB((player) => - createTokenDB(player, type, (newToken) => next(newToken)) + createTokenDB(player, type, (newToken) => { + // Set login cookie + setCookie("token", newToken.value, { + req, + res, + maxAge: 172800, + httpOnly: true, + sameSite: true, + secure: true, + path: "/api", + }) + return next(newToken) + }) ) } return next({ value, type }) diff --git a/leaky-ships/lib/hooks/useGameEvent.ts b/leaky-ships/lib/hooks/useGameEvent.tsx similarity index 87% rename from leaky-ships/lib/hooks/useGameEvent.ts rename to leaky-ships/lib/hooks/useGameEvent.tsx index 6202eee..72ccbab 100644 --- a/leaky-ships/lib/hooks/useGameEvent.ts +++ b/leaky-ships/lib/hooks/useGameEvent.tsx @@ -1,4 +1,8 @@ +import BorderTiles from "../../components/Gamefield/BorderTiles" +import EventBar from "../../components/Gamefield/EventBar" import type { PointerProps } from "../../components/Gamefield/GamefieldPointer" +import HitElems from "../../components/Gamefield/HitElems" +import Targets from "../../components/Gamefield/Targets" import { Hit, Mode, @@ -6,6 +10,7 @@ import { Target, Position, } from "../../interfaces/frontend" +import { gameContext } from "../../pages/_app" import { hitReducer, initlialLastLeftTile, @@ -13,7 +18,7 @@ import { initlialTargetPreview, initlialMouseCursor, } from "../utils/helpers" -import { useCallback, useEffect, useReducer, useState } from "react" +import { useCallback, useContext, useEffect, useReducer, useState } from "react" const modes: Mode[] = [ { @@ -28,10 +33,14 @@ const modes: Mode[] = [ pointerGrid: Array.from(Array(1), () => Array.from(Array(3))), type: "vtorpedo", }, - { pointerGrid: [[{ x: 0, y: 0 }]], type: "missile" }, + { + pointerGrid: Array.from(Array(1), () => Array.from(Array(1))), + type: "missile", + }, ] function useGameEvent(count: number) { + const [gameProps, setGameProps] = useContext(gameContext) const [lastLeftTile, setLastLeftTile] = useState(initlialLastLeftTile) const [target, setTarget] = useState(initlialTarget) @@ -208,10 +217,16 @@ function useGameEvent(count: number) { }, [targetPreview.show]) return { - tilesProps: { count, settingTarget, setMouseCursor, setLastLeftTile }, - pointersProps: { composeTargetTiles, target, targetPreview }, - targetsProps: { setMode, setTarget }, - hits, + BorderTiles: () => ( + + ), + HitElems: () => , + Targets: () => ( + + ), + EventBar: () => , } } diff --git a/leaky-ships/package.json b/leaky-ships/package.json index a087ed0..3949f52 100644 --- a/leaky-ships/package.json +++ b/leaky-ships/package.json @@ -32,7 +32,8 @@ "react-dom": "18.2.0", "socket.io": "^4.6.1", "socket.io-client": "^4.6.1", - "typescript": "4.9.4" + "typescript": "4.9.4", + "zod": "^3.21.4" }, "devDependencies": { "@total-typescript/ts-reset": "^0.3.7", diff --git a/leaky-ships/pages/_app.tsx b/leaky-ships/pages/_app.tsx index a257dd8..821c654 100644 --- a/leaky-ships/pages/_app.tsx +++ b/leaky-ships/pages/_app.tsx @@ -3,7 +3,28 @@ import "../styles/globals.css" import "../styles/grid2.scss" import "../styles/grid.scss" import type { AppProps } from "next/app" +import { Dispatch, SetStateAction, createContext, useState } from "react" + +interface gameContext { + pin?: string + game?: { + id: "" + } + enemy?: { + id: string + username?: string + } +} + +export const gameContext = createContext< + [gameContext, Dispatch>] +>([{}, () => {}]) export default function App({ Component, pageProps }: AppProps) { - return + const gameProps = useState({}) + return ( + + + + ) } diff --git a/leaky-ships/pages/api/game/create.ts b/leaky-ships/pages/api/game/create.ts index a12f084..f03b900 100644 --- a/leaky-ships/pages/api/game/create.ts +++ b/leaky-ships/pages/api/game/create.ts @@ -2,12 +2,18 @@ import sendError from "@backend/components/sendError" import sendResponse from "@backend/components/sendResponse" import getPlayer from "@lib/backend/components/getPlayer" import prisma from "@lib/prisma" -import type { Game } from "@prisma/client" import type { NextApiRequest, NextApiResponse } from "next" +import { z } from "zod" -interface Data { - game: Game -} +const returnSchema = z.object({ + game: z.object({ + id: z.string(), + createdAt: z.date(), + updatedAt: z.date(), + running: z.boolean(), + }), +}) +type Data = z.infer export default async function create( req: NextApiRequest, diff --git a/leaky-ships/pages/api/user/auth.ts b/leaky-ships/pages/api/user/auth.ts index 2fb0fd5..af98864 100644 --- a/leaky-ships/pages/api/user/auth.ts +++ b/leaky-ships/pages/api/user/auth.ts @@ -18,19 +18,19 @@ export default async function auth( const context = { req, res } const type = "ACCESS" - getTokenFromCookie(context, (refreshToken) => { - checkTokenIsValid(context, refreshToken, (token) => { - getTokenDB(context, token, (tokenDB) => { - getPlayerByIdDB(context, tokenDB, (player) => { - createTokenDB(player, type, (newToken, newTokenDB) => { + return getTokenFromCookie(context, (refreshToken) => + checkTokenIsValid(context, refreshToken, (token) => + getTokenDB(context, token, (tokenDB) => + getPlayerByIdDB(context, tokenDB, (player) => + createTokenDB(player, type, (newToken, newTokenDB) => sendResponse(context, { message: `Access-Token generated: ${newTokenDB.id} with Refreshtoken-Token: ${tokenDB.id}`, body: { token: newToken.value }, type: ["debug", "infoCyan"], }) - }) - }) - }) - }) - }).catch((err) => sendError(context, err)) + ) + ) + ) + ) + ).catch((err) => sendError(context, err)) } diff --git a/leaky-ships/pages/api/user/logout.ts b/leaky-ships/pages/api/user/logout.ts index 13e6643..d479186 100644 --- a/leaky-ships/pages/api/user/logout.ts +++ b/leaky-ships/pages/api/user/logout.ts @@ -1,8 +1,8 @@ -import checkTokenIsValid from "@backend/components/checkTokenIsValid" import getTokenDB from "@backend/components/getTokenDB" import getTokenFromCookie from "@backend/components/getTokenFromCookie" import sendError from "@backend/components/sendError" import sendResponse from "@backend/components/sendResponse" +import decodeToken from "@lib/backend/components/decodeToken" import { deleteCookie } from "cookies-next" import type { NextApiRequest, NextApiResponse } from "next" @@ -16,18 +16,23 @@ export default async function logout( ) { const context = { req, res } - return getTokenFromCookie(context, (refreshToken) => { - checkTokenIsValid(context, refreshToken, (token) => { - getTokenDB(context, token, (tokenDB) => { - // Set login cookie - deleteCookie("token", { req, res }) + return getTokenFromCookie(context, (refreshToken) => + decodeToken(context, refreshToken, (token) => + getTokenDB( + context, + token, + (tokenDB) => { + // Set login cookie + deleteCookie("token", { req, res }) - sendResponse(context, { - message: "User of Token " + tokenDB.id + " logged out.", - body: { loggedOut: true }, - type: ["debug", "infoCyan"], - }) - }) - }) - }).catch((err) => sendError(context, err)) + return sendResponse(context, { + message: "User of Token " + tokenDB.id + " logged out.", + body: { loggedOut: true }, + type: ["debug", "infoCyan"], + }) + }, + true + ) + ) + ).catch((err) => sendError(context, err)) } diff --git a/leaky-ships/pages/dev/index.tsx b/leaky-ships/pages/dev/index.tsx index 9afb65f..0519f32 100644 --- a/leaky-ships/pages/dev/index.tsx +++ b/leaky-ships/pages/dev/index.tsx @@ -6,18 +6,23 @@ import { faPlus, faUserPlus } from "@fortawesome/pro-solid-svg-icons" import { faCirclePlay } from "@fortawesome/pro-thin-svg-icons" import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" import getAccessToken from "@lib/frontend/getAccessToken" +import { GetServerSideProps } from "next" import { useRouter } from "next/router" import { useState } from "react" +import { z } from "zod" -export default function Home() { +interface Props { + start: boolean +} + +export default function Home({ start }: Props) { const router = useRouter() - const [heWantsToPlay, setHeWantsToPlay] = useState(false) return (
- {!heWantsToPlay ? ( + {!start ? ( <>
@@ -36,7 +49,14 @@ export default function Home() {
@@ -48,6 +68,25 @@ export default function Home() { method: "POST", body: JSON.stringify({ token }), }) + const gameSchema = z.object({ + game: z.object({ + id: z.string(), + createdAt: z.date(), + updatedAt: z.date(), + running: z.boolean(), + }), + }) + + const check = gameSchema.safeParse(game) + + if (check.success) { + const gameData = check.data + console.log(gameData) + } else { + console.error(check.error) + } + + // const warst = result.game router.push("/dev/lobby") }} @@ -64,3 +103,14 @@ export default function Home() {
) } + +export const getServerSideProps: GetServerSideProps = async ( + context +) => { + const { start } = context.query + + // Convert the `start` query parameter to a boolean + const isStart = start === "true" + + return { props: { start: isStart } } +} diff --git a/leaky-ships/pnpm-lock.yaml b/leaky-ships/pnpm-lock.yaml index 7944392..eea794c 100644 --- a/leaky-ships/pnpm-lock.yaml +++ b/leaky-ships/pnpm-lock.yaml @@ -73,6 +73,9 @@ dependencies: typescript: specifier: 4.9.4 version: 4.9.4 + zod: + specifier: ^3.21.4 + version: 3.21.4 devDependencies: '@total-typescript/ts-reset': @@ -3397,3 +3400,7 @@ packages: /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + + /zod@3.21.4: + resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} + dev: false