Backend rewrite using async/await
This commit is contained in:
parent
2862f94f1c
commit
549d0f1d77
26 changed files with 259 additions and 322 deletions
|
@ -6,12 +6,11 @@ import bcrypt from "bcrypt"
|
||||||
export default async function checkPasswordIsValid<T>(
|
export default async function checkPasswordIsValid<T>(
|
||||||
context: API<T>,
|
context: API<T>,
|
||||||
player: Player,
|
player: Player,
|
||||||
password: string,
|
password: string
|
||||||
next: () => void
|
|
||||||
) {
|
) {
|
||||||
// Validate for correct password
|
// Validate for correct password
|
||||||
const result = await bcrypt.compare(password, player.passwordHash ?? "")
|
const result = await bcrypt.compare(password, player.passwordHash ?? "")
|
||||||
if (!result) return sendError(context, rejectionErrors.wrongPassword)
|
if (!result) throw sendError(context, rejectionErrors.wrongPassword)
|
||||||
|
|
||||||
return next()
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,7 @@ import type { IdToken, RawToken } from "./createTokenDB"
|
||||||
import sendError, { API } from "./sendError"
|
import sendError, { API } from "./sendError"
|
||||||
import jwt from "jsonwebtoken"
|
import jwt from "jsonwebtoken"
|
||||||
|
|
||||||
async function checkTokenIsValid<T>(
|
async function checkTokenIsValid<T>(context: API<T>, rawToken: RawToken) {
|
||||||
context: API<T>,
|
|
||||||
rawToken: RawToken,
|
|
||||||
next: (token: IdToken) => void
|
|
||||||
) {
|
|
||||||
const { value, type } = rawToken
|
const { value, type } = rawToken
|
||||||
|
|
||||||
// Verify the token and get the payload
|
// Verify the token and get the payload
|
||||||
|
@ -17,13 +13,13 @@ async function checkTokenIsValid<T>(
|
||||||
data = jwt.verify(value, process.env.TOKEN_SECRET as string)
|
data = jwt.verify(value, process.env.TOKEN_SECRET as string)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
// Deal with the problem in more detail
|
// Deal with the problem in more detail
|
||||||
return sendError(context, jwtVerifyCatch(type, err))
|
throw sendError(context, jwtVerifyCatch(type, err))
|
||||||
}
|
}
|
||||||
// Making sure the token data is not a string (because it should be an object)
|
// Making sure the token data is not a string (because it should be an object)
|
||||||
if (typeof data === "string")
|
if (typeof data === "string")
|
||||||
return sendError(context, rejectionErrorFns.tokenWasString(type, value))
|
throw sendError(context, rejectionErrorFns.tokenWasString(type, value))
|
||||||
|
|
||||||
return next({ id: data.id, type })
|
return { id: data.id, type }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default checkTokenIsValid
|
export default checkTokenIsValid
|
||||||
|
|
|
@ -2,11 +2,11 @@ import prisma from "../../prisma"
|
||||||
import logging from "../logging"
|
import logging from "../logging"
|
||||||
import type { Player } from "@prisma/client"
|
import type { Player } from "@prisma/client"
|
||||||
|
|
||||||
async function createPlayerDB(next: (player: Player) => void) {
|
async function createPlayerDB() {
|
||||||
const player = await prisma.player.create({ data: {} })
|
const player = await prisma.player.create({ data: {} })
|
||||||
logging("Anonymous player created: " + player.id, ["debug"])
|
logging("Anonymous player created: " + player.id, ["debug"])
|
||||||
|
|
||||||
return next(player)
|
return player
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createPlayerDB
|
export default createPlayerDB
|
||||||
|
|
|
@ -18,8 +18,7 @@ export const tokenLifetime = {
|
||||||
|
|
||||||
export default async function createTokenDB(
|
export default async function createTokenDB(
|
||||||
player: Player,
|
player: Player,
|
||||||
newTokenType: TokenType,
|
newTokenType: TokenType
|
||||||
next: (newToken: RawToken, newTokenDB: Token) => void
|
|
||||||
) {
|
) {
|
||||||
// Create token entry in DB
|
// Create token entry in DB
|
||||||
const newTokenDB = await prisma.token.create({
|
const newTokenDB = await prisma.token.create({
|
||||||
|
@ -41,5 +40,5 @@ export default async function createTokenDB(
|
||||||
{ expiresIn: tokenLifetime[newTokenType] }
|
{ expiresIn: tokenLifetime[newTokenType] }
|
||||||
)
|
)
|
||||||
|
|
||||||
return next({ value: newToken, type: newTokenType }, newTokenDB)
|
return { newToken: { value: newToken, type: newTokenType }, newTokenDB }
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,7 @@ import type { IdToken, RawToken } from "./createTokenDB"
|
||||||
import sendError, { API } from "./sendError"
|
import sendError, { API } from "./sendError"
|
||||||
import jwt from "jsonwebtoken"
|
import jwt from "jsonwebtoken"
|
||||||
|
|
||||||
async function decodeToken<T>(
|
async function decodeToken<T>(context: API<T>, rawToken: RawToken) {
|
||||||
context: API<T>,
|
|
||||||
rawToken: RawToken,
|
|
||||||
next: (token: IdToken) => void
|
|
||||||
) {
|
|
||||||
const { value, type } = rawToken
|
const { value, type } = rawToken
|
||||||
|
|
||||||
// Verify the token and get the payload
|
// Verify the token and get the payload
|
||||||
|
@ -22,14 +18,14 @@ async function decodeToken<T>(
|
||||||
const fallbackData = jwt.decode(value)
|
const fallbackData = jwt.decode(value)
|
||||||
// Making sure the token data is not a string (because it should be an object)
|
// Making sure the token data is not a string (because it should be an object)
|
||||||
if (typeof fallbackData === "string")
|
if (typeof fallbackData === "string")
|
||||||
return sendError(context, rejectionErrorFns.tokenWasString(type, value))
|
throw sendError(context, rejectionErrorFns.tokenWasString(type, value))
|
||||||
return next({ id: fallbackData?.id, type })
|
return { id: fallbackData?.id, type }
|
||||||
}
|
}
|
||||||
// Making sure the token data is not a string (because it should be an object)
|
// Making sure the token data is not a string (because it should be an object)
|
||||||
if (typeof data === "string")
|
if (typeof data === "string")
|
||||||
return sendError(context, rejectionErrorFns.tokenWasString(type, value))
|
throw sendError(context, rejectionErrorFns.tokenWasString(type, value))
|
||||||
|
|
||||||
return next({ id: data.id, type })
|
return { id: data.id, type }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default decodeToken
|
export default decodeToken
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import sendError, { API } from "./sendError"
|
import sendError, { API } from "./sendError"
|
||||||
|
|
||||||
async function getPinFromBody<T>(context: API<T>, next: (pin: string) => void) {
|
async function getPinFromBody<T>(context: API<T>) {
|
||||||
const body = JSON.parse(context.req.body)
|
const body = JSON.parse(context.req.body)
|
||||||
if (
|
if (
|
||||||
typeof body !== "object" ||
|
typeof body !== "object" ||
|
||||||
|
@ -8,7 +8,7 @@ async function getPinFromBody<T>(context: API<T>, next: (pin: string) => void) {
|
||||||
!("pin" in body) ||
|
!("pin" in body) ||
|
||||||
typeof body.pin !== "string"
|
typeof body.pin !== "string"
|
||||||
)
|
)
|
||||||
return sendError(context, {
|
throw sendError(context, {
|
||||||
rejected: true,
|
rejected: true,
|
||||||
message: "No pin in request body!",
|
message: "No pin in request body!",
|
||||||
statusCode: 401,
|
statusCode: 401,
|
||||||
|
@ -17,7 +17,7 @@ async function getPinFromBody<T>(context: API<T>, next: (pin: string) => void) {
|
||||||
})
|
})
|
||||||
const { pin } = body
|
const { pin } = body
|
||||||
|
|
||||||
return next(pin)
|
return pin
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getPinFromBody
|
export default getPinFromBody
|
||||||
|
|
|
@ -3,19 +3,13 @@ import getPlayerByIdDB from "./getPlayerByIdDB"
|
||||||
import getTokenDB from "./getTokenDB"
|
import getTokenDB from "./getTokenDB"
|
||||||
import getTokenFromBody from "./getTokenFromBody"
|
import getTokenFromBody from "./getTokenFromBody"
|
||||||
import { API } from "./sendError"
|
import { API } from "./sendError"
|
||||||
import { Player, Token } from "@prisma/client"
|
|
||||||
|
|
||||||
function getPlayer<T>(
|
async function getPlayer<T>(context: API<T>) {
|
||||||
context: API<T>,
|
const accessToken = await getTokenFromBody(context)
|
||||||
next: (player: Player, tokenDB: Token) => void
|
const token = await checkTokenIsValid(context, accessToken)
|
||||||
) {
|
const tokenDB = await getTokenDB(context, token)
|
||||||
return getTokenFromBody(context, (accessToken) => {
|
const player = await getPlayerByIdDB(context, tokenDB)
|
||||||
checkTokenIsValid(context, accessToken, (token) => {
|
return { player, tokenDB }
|
||||||
getTokenDB(context, token, (tokenDB) => {
|
|
||||||
getPlayerByIdDB(context, tokenDB, (player) => next(player, tokenDB))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getPlayer
|
export default getPlayer
|
||||||
|
|
|
@ -5,8 +5,7 @@ import type { Player, Token } from "@prisma/client"
|
||||||
|
|
||||||
export default async function getPlayerByIdDB<T>(
|
export default async function getPlayerByIdDB<T>(
|
||||||
context: API<T>,
|
context: API<T>,
|
||||||
tokenDB: Token,
|
tokenDB: Token
|
||||||
next: (player: Player) => void
|
|
||||||
) {
|
) {
|
||||||
// Find Host in DB if it still exists (just to make sure)
|
// Find Host in DB if it still exists (just to make sure)
|
||||||
const player = await prisma.player.findUnique({
|
const player = await prisma.player.findUnique({
|
||||||
|
@ -15,8 +14,8 @@ export default async function getPlayerByIdDB<T>(
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if (!player) {
|
if (!player) {
|
||||||
return sendError(context, rejectionErrors.playerNotFound)
|
throw sendError(context, rejectionErrors.playerNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(player)
|
return player
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ import type { Player } from "@prisma/client"
|
||||||
|
|
||||||
export default async function getPlayerByNameDB<T>(
|
export default async function getPlayerByNameDB<T>(
|
||||||
context: API<T>,
|
context: API<T>,
|
||||||
username: string,
|
username: string
|
||||||
next: (player: Player) => void
|
|
||||||
) {
|
) {
|
||||||
// Find Player in DB if it still exists (just to make sure)
|
// Find Player in DB if it still exists (just to make sure)
|
||||||
const player = await Promise.any([
|
const player = await Promise.any([
|
||||||
|
@ -21,7 +20,7 @@ export default async function getPlayerByNameDB<T>(
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]).catch(() => null)
|
]).catch(() => null)
|
||||||
if (player === null) return sendError(context, rejectionErrors.playerNotFound)
|
if (player === null) throw sendError(context, rejectionErrors.playerNotFound)
|
||||||
|
|
||||||
return next(player)
|
return player
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,12 @@ import prisma from "../../prisma"
|
||||||
import { rejectionErrorFns, rejectionErrors } from "../errors"
|
import { rejectionErrorFns, rejectionErrors } from "../errors"
|
||||||
import type { IdToken } from "./createTokenDB"
|
import type { IdToken } from "./createTokenDB"
|
||||||
import sendError, { API } from "./sendError"
|
import sendError, { API } from "./sendError"
|
||||||
import type { Token } from "@prisma/client"
|
|
||||||
import { deleteCookie } from "cookies-next"
|
import { deleteCookie } from "cookies-next"
|
||||||
|
|
||||||
async function getTokenDB<T>(
|
async function getTokenDB<T>(
|
||||||
context: API<T>,
|
context: API<T>,
|
||||||
token: IdToken,
|
token: IdToken,
|
||||||
next: (tokenDB: Token) => void,
|
|
||||||
ignoreChecks?: boolean
|
ignoreChecks?: boolean
|
||||||
) {
|
) {
|
||||||
const { id, type } = token
|
const { id, type } = token
|
||||||
|
@ -20,11 +19,11 @@ async function getTokenDB<T>(
|
||||||
})
|
})
|
||||||
if (!tokenDB) {
|
if (!tokenDB) {
|
||||||
deleteCookie("token", { ...context, path: "/api" })
|
deleteCookie("token", { ...context, path: "/api" })
|
||||||
return sendError(context, rejectionErrorFns.tokenNotFound(type))
|
throw sendError(context, rejectionErrorFns.tokenNotFound(type))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenDB.used && !ignoreChecks)
|
if (tokenDB.used && !ignoreChecks)
|
||||||
return sendError(context, rejectionErrors.tokenUsed)
|
throw sendError(context, rejectionErrors.tokenUsed)
|
||||||
|
|
||||||
await prisma.token.update({
|
await prisma.token.update({
|
||||||
where: {
|
where: {
|
||||||
|
@ -37,7 +36,7 @@ async function getTokenDB<T>(
|
||||||
|
|
||||||
// await logging('Old token has been invalidated.', ['debug'], req)
|
// await logging('Old token has been invalidated.', ['debug'], req)
|
||||||
|
|
||||||
return next(tokenDB)
|
return tokenDB
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getTokenDB
|
export default getTokenDB
|
||||||
|
|
|
@ -2,10 +2,7 @@ import { rejectionErrorFns } from "../errors"
|
||||||
import type { RawToken } from "./createTokenDB"
|
import type { RawToken } from "./createTokenDB"
|
||||||
import sendError, { API } from "./sendError"
|
import sendError, { API } from "./sendError"
|
||||||
|
|
||||||
async function getTokenFromBody<T>(
|
async function getTokenFromBody<T>(context: API<T>): Promise<RawToken> {
|
||||||
context: API<T>,
|
|
||||||
next: (accessToken: RawToken) => void
|
|
||||||
) {
|
|
||||||
const type = "ACCESS"
|
const type = "ACCESS"
|
||||||
const body = JSON.parse(context.req.body)
|
const body = JSON.parse(context.req.body)
|
||||||
// Checking for cookie presens, because it is necessary
|
// Checking for cookie presens, because it is necessary
|
||||||
|
@ -16,11 +13,11 @@ async function getTokenFromBody<T>(
|
||||||
typeof body.token === "string"
|
typeof body.token === "string"
|
||||||
) {
|
) {
|
||||||
const value = body.token
|
const value = body.token
|
||||||
return next({ value, type })
|
return { value, type }
|
||||||
}
|
}
|
||||||
console.log(body)
|
console.log(body)
|
||||||
|
|
||||||
return sendError(context, rejectionErrorFns.noToken(type))
|
throw sendError(context, rejectionErrorFns.noToken(type))
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getTokenFromBody
|
export default getTokenFromBody
|
||||||
|
|
|
@ -3,25 +3,29 @@ import createTokenDB, { RawToken } from "./createTokenDB"
|
||||||
import type { API } from "./sendError"
|
import type { API } from "./sendError"
|
||||||
import { Player, Token } from "@prisma/client"
|
import { Player, Token } from "@prisma/client"
|
||||||
|
|
||||||
async function getTokenFromCookie<T>(
|
interface Returning {
|
||||||
context: API<T>,
|
refreshToken: RawToken
|
||||||
next: (
|
newPlayer?: { player: Player; newToken: RawToken; newTokenDB: Token }
|
||||||
refreshToken: RawToken,
|
}
|
||||||
newPlayer?: { player: Player; newToken: RawToken; newTokenDB: Token }
|
|
||||||
) => void
|
async function getTokenFromCookie<T>(context: API<T>): Promise<Returning> {
|
||||||
) {
|
|
||||||
const type = "REFRESH"
|
const type = "REFRESH"
|
||||||
const value = context.req.cookies.token
|
const value = context.req.cookies.token
|
||||||
|
|
||||||
// Checking for cookie presens, because it is necessary
|
// Checking for cookie presens, because it is necessary
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return createPlayerDB((player) =>
|
const player = await createPlayerDB()
|
||||||
createTokenDB(player, type, (newToken, newTokenDB) =>
|
const { newToken, newTokenDB } = await createTokenDB(player, type)
|
||||||
next(newToken, { player, newToken, newTokenDB })
|
return {
|
||||||
)
|
refreshToken: newToken,
|
||||||
)
|
newPlayer: {
|
||||||
|
player,
|
||||||
|
newToken,
|
||||||
|
newTokenDB,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return next({ value, type })
|
return { refreshToken: { value, type } }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getTokenFromCookie
|
export default getTokenFromCookie
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import { rejectionErrors } from "../errors"
|
import { rejectionErrors } from "../errors"
|
||||||
import sendError, { API } from "./sendError"
|
import sendError, { API } from "./sendError"
|
||||||
|
|
||||||
async function getUserFromBody<T>(
|
async function getUserFromBody<T>(context: API<T>) {
|
||||||
context: API<T>,
|
|
||||||
next: (username: string, password: string) => void
|
|
||||||
) {
|
|
||||||
const body = JSON.parse(context.req.body)
|
const body = JSON.parse(context.req.body)
|
||||||
if (
|
if (
|
||||||
typeof body !== "object" ||
|
typeof body !== "object" ||
|
||||||
|
@ -12,13 +9,13 @@ async function getUserFromBody<T>(
|
||||||
!("username" in body) ||
|
!("username" in body) ||
|
||||||
typeof body.username !== "string"
|
typeof body.username !== "string"
|
||||||
)
|
)
|
||||||
return sendError(context, rejectionErrors.noUsername)
|
throw sendError(context, rejectionErrors.noUsername)
|
||||||
const { username } = body
|
const { username } = body
|
||||||
if (!("password" in body) || typeof body.password !== "string")
|
if (!("password" in body) || typeof body.password !== "string")
|
||||||
return sendError(context, rejectionErrors.noPassword)
|
throw sendError(context, rejectionErrors.noPassword)
|
||||||
const { password } = body
|
const { password } = body
|
||||||
|
|
||||||
return next(username, password)
|
return { username, password }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getUserFromBody
|
export default getUserFromBody
|
||||||
|
|
|
@ -37,4 +37,5 @@ export default function sendResponse<T>(context: API<T>, result: Result<T>) {
|
||||||
res.status(result.statusCode ?? 200)
|
res.status(result.statusCode ?? 200)
|
||||||
result.body ? res.json(result.body) : res.end()
|
result.body ? res.json(result.body) : res.end()
|
||||||
logging(result.message, result.type ?? ["debug"], req)
|
logging(result.message, result.type ?? ["debug"], req)
|
||||||
|
return "done" as const
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,15 @@ import type { Player, Prisma } from "@prisma/client"
|
||||||
async function updatePlayerDB<T>(
|
async function updatePlayerDB<T>(
|
||||||
context: API<T>,
|
context: API<T>,
|
||||||
player: Player,
|
player: Player,
|
||||||
data: Prisma.PlayerUpdateInput,
|
data: Prisma.PlayerUpdateInput
|
||||||
next: (updatedPlayer: Player) => void
|
|
||||||
) {
|
) {
|
||||||
if (!player.anonymous) return sendError(context, rejectionErrors.registered)
|
if (!player.anonymous) throw sendError(context, rejectionErrors.registered)
|
||||||
const updatedPlayer = await prisma.player.update({
|
const updatedPlayer = await prisma.player.update({
|
||||||
where: { id: player.id },
|
where: { id: player.id },
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
|
||||||
return next(updatedPlayer)
|
return updatedPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
export default updatePlayerDB
|
export default updatePlayerDB
|
||||||
|
|
|
@ -28,7 +28,7 @@ async function getAccessToken() {
|
||||||
.then(successfulResponse)
|
.then(successfulResponse)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
try {
|
try {
|
||||||
const token = tokenSchema.parse(response)
|
const { token } = tokenSchema.parse(response)
|
||||||
|
|
||||||
return token
|
return token
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import sendError from "@backend/components/sendError"
|
|
||||||
import sendResponse from "@backend/components/sendResponse"
|
import sendResponse from "@backend/components/sendResponse"
|
||||||
import getPlayer from "@lib/backend/components/getPlayer"
|
import getPlayer from "@lib/backend/components/getPlayer"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import { Game, Gamepin, Player_Game } from "@prisma/client"
|
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
@ -36,25 +34,40 @@ export default async function create(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return getPlayer(context, async (player) => {
|
const { player } = await getPlayer(context)
|
||||||
// Generate a random 4-digit code
|
// Generate a random 4-digit code
|
||||||
const pin = Math.floor(Math.random() * 10000)
|
const pin = Math.floor(Math.random() * 10000)
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(4, "0")
|
.padStart(4, "0")
|
||||||
|
|
||||||
let created = false
|
let created = false
|
||||||
let game:
|
|
||||||
| (Game & {
|
|
||||||
pin: Gamepin | null
|
|
||||||
players: Player_Game[]
|
|
||||||
})
|
|
||||||
| null
|
|
||||||
|
|
||||||
game = await prisma.game.findFirst({
|
let game = await prisma.game.findFirst({
|
||||||
where: {
|
where: {
|
||||||
running: true,
|
running: true,
|
||||||
|
players: {
|
||||||
|
some: {
|
||||||
|
playerId: player.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
pin: true,
|
||||||
|
players: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (!game) {
|
||||||
|
created = true
|
||||||
|
game = await prisma.game.create({
|
||||||
|
data: {
|
||||||
|
pin: {
|
||||||
|
create: {
|
||||||
|
pin,
|
||||||
|
},
|
||||||
|
},
|
||||||
players: {
|
players: {
|
||||||
some: {
|
create: {
|
||||||
|
isOwner: true,
|
||||||
playerId: player.id,
|
playerId: player.id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -64,42 +77,20 @@ export default async function create(
|
||||||
players: true,
|
players: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if (!game) {
|
}
|
||||||
created = true
|
|
||||||
game = await prisma.game.create({
|
|
||||||
data: {
|
|
||||||
pin: {
|
|
||||||
create: {
|
|
||||||
pin,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
players: {
|
|
||||||
create: {
|
|
||||||
isOwner: true,
|
|
||||||
playerId: player.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
pin: true,
|
|
||||||
players: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return sendResponse(context, {
|
return sendResponse(context, {
|
||||||
message: `Player: ${player.id} created game: ${game.id}`,
|
message: `Player: ${player.id} created game: ${game.id}`,
|
||||||
statusCode: created ? 201 : 200,
|
statusCode: created ? 201 : 200,
|
||||||
body: {
|
body: {
|
||||||
game,
|
game,
|
||||||
pin: game.pin?.pin,
|
pin: game.pin?.pin,
|
||||||
player: {
|
player: {
|
||||||
id: player.id,
|
id: player.id,
|
||||||
username: player.username ?? undefined,
|
username: player.username ?? undefined,
|
||||||
isOwner: true,
|
isOwner: true,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
type: ["debug", "infoCyan"],
|
},
|
||||||
})
|
type: ["debug", "infoCyan"],
|
||||||
}).catch((err) => sendError(context, err))
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,63 +17,61 @@ export default async function join(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return getPinFromBody(context, (pin) =>
|
const pin = await getPinFromBody(context)
|
||||||
getPlayer(context, async (player) => {
|
const { player } = await getPlayer(context)
|
||||||
try {
|
try {
|
||||||
const pinDB = await prisma.gamepin.update({
|
const pinDB = await prisma.gamepin.update({
|
||||||
where: {
|
where: {
|
||||||
pin,
|
pin,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
game: {
|
game: {
|
||||||
update: {
|
update: {
|
||||||
players: {
|
players: {
|
||||||
create: {
|
create: {
|
||||||
isOwner: false,
|
isOwner: false,
|
||||||
playerId: player.id,
|
playerId: player.id,
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
game: {
|
||||||
include: {
|
include: {
|
||||||
game: {
|
players: {
|
||||||
include: {
|
include: {
|
||||||
players: {
|
player: true,
|
||||||
include: {
|
|
||||||
player: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
},
|
||||||
const enemy = pinDB.game.players.find(
|
|
||||||
(enemy) => enemy.player.id !== player.id
|
|
||||||
)
|
|
||||||
return sendResponse(context, {
|
|
||||||
message: `Player: ${player.id} joined game: ${pinDB.game.id}`,
|
|
||||||
body: {
|
|
||||||
game: pinDB.game,
|
|
||||||
pin: pinDB.pin,
|
|
||||||
player: {
|
|
||||||
id: player.id,
|
|
||||||
username: player.username ?? undefined,
|
|
||||||
isOwner: true,
|
|
||||||
},
|
|
||||||
enemy: {
|
|
||||||
id: enemy?.player.id,
|
|
||||||
username: enemy?.player.username ?? undefined,
|
|
||||||
isOwner: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
type: ["debug", "infoCyan"],
|
|
||||||
})
|
|
||||||
} catch (err: any) {
|
|
||||||
console.log("HERE".red, err.code, err.meta, err.message)
|
|
||||||
return sendError(context, rejectionErrors.gameNotFound)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
).catch((err) => sendError(context, err))
|
|
||||||
|
const enemy = pinDB.game.players.find(
|
||||||
|
(enemy) => enemy.player.id !== player.id
|
||||||
|
)
|
||||||
|
return sendResponse(context, {
|
||||||
|
message: `Player: ${player.id} joined game: ${pinDB.game.id}`,
|
||||||
|
body: {
|
||||||
|
game: pinDB.game,
|
||||||
|
pin: pinDB.pin,
|
||||||
|
player: {
|
||||||
|
id: player.id,
|
||||||
|
username: player.username ?? undefined,
|
||||||
|
isOwner: true,
|
||||||
|
},
|
||||||
|
enemy: {
|
||||||
|
id: enemy?.player.id,
|
||||||
|
username: enemy?.player.username ?? undefined,
|
||||||
|
isOwner: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
type: ["debug", "infoCyan"],
|
||||||
|
})
|
||||||
|
} catch (err: any) {
|
||||||
|
console.log("HERE".red, err.code, err.meta, err.message)
|
||||||
|
throw sendError(context, rejectionErrors.gameNotFound)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,24 +19,25 @@ export default async function auth(
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
const type = "ACCESS"
|
const type = "ACCESS"
|
||||||
|
|
||||||
return getTokenFromCookie(context, (refreshToken, newPlayer) => {
|
const { refreshToken, newPlayer } = await getTokenFromCookie(context)
|
||||||
const next = (player: Player, tokenDB: Token, cookie?: string) =>
|
|
||||||
createTokenDB(player, type, (newToken, newTokenDB) =>
|
let player: Player, tokenDB: Token, cookie: string | undefined
|
||||||
sendResponse(context, {
|
|
||||||
message: `Access-Token generated: ${newTokenDB.id} with Refreshtoken-Token: ${tokenDB.id}`,
|
if (!newPlayer) {
|
||||||
body: { token: newToken.value },
|
const token = await checkTokenIsValid(context, refreshToken)
|
||||||
type: ["debug", "infoCyan"],
|
tokenDB = await getTokenDB(context, token)
|
||||||
cookie,
|
player = await getPlayerByIdDB(context, tokenDB)
|
||||||
})
|
} else {
|
||||||
)
|
player = newPlayer.player
|
||||||
if (!newPlayer) {
|
tokenDB = newPlayer.newTokenDB
|
||||||
return checkTokenIsValid(context, refreshToken, (token) =>
|
cookie = newPlayer.newToken.value
|
||||||
getTokenDB(context, token, (tokenDB) =>
|
}
|
||||||
getPlayerByIdDB(context, tokenDB, (player) => next(player, tokenDB))
|
|
||||||
)
|
const { newToken, newTokenDB } = await createTokenDB(player, type)
|
||||||
)
|
return sendResponse(context, {
|
||||||
}
|
message: `Access-Token generated: ${newTokenDB.id} with Refreshtoken-Token: ${tokenDB.id}`,
|
||||||
const { player, newToken, newTokenDB } = newPlayer
|
body: { token: newToken.value },
|
||||||
return next(player, newTokenDB, newToken.value)
|
type: ["debug", "infoCyan"],
|
||||||
}).catch((err) => sendError(context, err))
|
cookie,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import sendError from "@backend/components/sendError"
|
|
||||||
import sendResponse from "@backend/components/sendResponse"
|
import sendResponse from "@backend/components/sendResponse"
|
||||||
import getPlayer from "@lib/backend/components/getPlayer"
|
import getPlayer from "@lib/backend/components/getPlayer"
|
||||||
import type { Game } from "@prisma/client"
|
import type { Game } from "@prisma/client"
|
||||||
|
@ -14,12 +13,11 @@ export default async function data(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return getPlayer(context, (player, tokenDB) => {
|
const { player, tokenDB } = await getPlayer(context)
|
||||||
const games: any = {}
|
const games: any = {}
|
||||||
sendResponse(context, {
|
return sendResponse(context, {
|
||||||
message: `Requested data of user: ${player.id} with Access-Token: ${tokenDB.id}`,
|
message: `Requested data of user: ${player.id} with Access-Token: ${tokenDB.id}`,
|
||||||
body: { games },
|
body: { games },
|
||||||
type: ["debug", "infoCyan"],
|
type: ["debug", "infoCyan"],
|
||||||
})
|
})
|
||||||
}).catch((err) => sendError(context, err))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import sendResponse from "@backend/components/sendResponse"
|
||||||
import logging from "@backend/logging"
|
import logging from "@backend/logging"
|
||||||
import { rejectionErrors } from "@lib/backend/errors"
|
import { rejectionErrors } from "@lib/backend/errors"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import { setCookie } from "cookies-next"
|
|
||||||
import jwt from "jsonwebtoken"
|
import jwt from "jsonwebtoken"
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
@ -21,34 +20,29 @@ export default async function login(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return preCheck(context, () =>
|
await preCheck(context)
|
||||||
getUserFromBody(context, (username, password) =>
|
const { username, password } = await getUserFromBody(context)
|
||||||
getPlayerByNameDB(context, username, (player) => {
|
const player = await getPlayerByNameDB(context, username)
|
||||||
checkPasswordIsValid(context, player, password, () => {
|
await checkPasswordIsValid(context, player, password)
|
||||||
createTokenDB(player, "REFRESH", (newToken, newTokenDB) => {
|
const { newToken, newTokenDB } = await createTokenDB(player, "REFRESH")
|
||||||
sendResponse(context, {
|
return sendResponse(context, {
|
||||||
message:
|
message:
|
||||||
"User " +
|
"User " +
|
||||||
player.id +
|
player.id +
|
||||||
" logged in and generated Refresh-Token: " +
|
" logged in and generated Refresh-Token: " +
|
||||||
newTokenDB.id,
|
newTokenDB.id,
|
||||||
body: { loggedIn: true },
|
body: { loggedIn: true },
|
||||||
type: ["debug", "infoCyan"],
|
type: ["debug", "infoCyan"],
|
||||||
cookie: newToken.value,
|
cookie: newToken.value,
|
||||||
})
|
})
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
).catch((err) => sendError(context, err))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function preCheck<T>(context: API<T>, next: () => void) {
|
async function preCheck<T>(context: API<T>) {
|
||||||
const { req } = context
|
const { req } = context
|
||||||
const oldRefreshToken = req.cookies.token
|
const oldRefreshToken = req.cookies.token
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!oldRefreshToken) return sendError(context, rejectionErrors.noCookie)
|
if (!oldRefreshToken) throw sendError(context, rejectionErrors.noCookie)
|
||||||
// Check for old cookie, if unused invalidate it
|
// Check for old cookie, if unused invalidate it
|
||||||
const tokenData = jwt.verify(
|
const tokenData = jwt.verify(
|
||||||
oldRefreshToken,
|
oldRefreshToken,
|
||||||
|
@ -80,5 +74,5 @@ async function preCheck<T>(context: API<T>, next: () => void) {
|
||||||
// err is expected if no correct cookie, just continue, otherwise it has been invalidated above
|
// err is expected if no correct cookie, just continue, otherwise it has been invalidated above
|
||||||
}
|
}
|
||||||
|
|
||||||
return next()
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import checkTokenIsValid from "@backend/components/checkTokenIsValid"
|
||||||
import getPlayerByIdDB from "@backend/components/getPlayerByIdDB"
|
import getPlayerByIdDB from "@backend/components/getPlayerByIdDB"
|
||||||
import getTokenDB from "@backend/components/getTokenDB"
|
import getTokenDB from "@backend/components/getTokenDB"
|
||||||
import getTokenFromCookie from "@backend/components/getTokenFromCookie"
|
import getTokenFromCookie from "@backend/components/getTokenFromCookie"
|
||||||
import sendError from "@backend/components/sendError"
|
|
||||||
import sendResponse from "@backend/components/sendResponse"
|
import sendResponse from "@backend/components/sendResponse"
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
@ -16,16 +15,12 @@ export default async function auth(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
getTokenFromCookie(context, (refreshToken) => {
|
const { refreshToken } = await getTokenFromCookie(context)
|
||||||
checkTokenIsValid(context, refreshToken, (token) => {
|
const token = await checkTokenIsValid(context, refreshToken)
|
||||||
getTokenDB(context, token, (tokenDB) => {
|
const tokenDB = await getTokenDB(context, token)
|
||||||
getPlayerByIdDB(context, tokenDB, (player) => {
|
const player = await getPlayerByIdDB(context, tokenDB)
|
||||||
sendResponse(context, {
|
return sendResponse(context, {
|
||||||
message: "loginCheck -> true : " + player.id,
|
message: "loginCheck -> true : " + player.id,
|
||||||
type: ["debug", "infoCyan"],
|
type: ["debug", "infoCyan"],
|
||||||
})
|
})
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).catch((err) => sendError(context, err))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,21 +15,14 @@ export default async function logout(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return getTokenFromCookie(context, (refreshToken) =>
|
const { refreshToken } = await getTokenFromCookie(context)
|
||||||
decodeToken(context, refreshToken, (token) =>
|
const token = await decodeToken(context, refreshToken)
|
||||||
getTokenDB(
|
const tokenDB = await getTokenDB(context, token, true)
|
||||||
context,
|
|
||||||
token,
|
return sendResponse(context, {
|
||||||
(tokenDB) => {
|
message: "User of Token " + tokenDB.id + " logged out.",
|
||||||
return sendResponse(context, {
|
body: { loggedOut: true },
|
||||||
message: "User of Token " + tokenDB.id + " logged out.",
|
type: ["debug", "infoCyan"],
|
||||||
body: { loggedOut: true },
|
cookie: "",
|
||||||
type: ["debug", "infoCyan"],
|
})
|
||||||
cookie: "",
|
|
||||||
})
|
|
||||||
},
|
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
).catch((err) => sendError(context, err))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,32 +19,22 @@ export default async function register(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return getTokenFromCookie(context, (refreshToken) => {
|
const { refreshToken } = await getTokenFromCookie(context)
|
||||||
checkTokenIsValid(context, refreshToken, (token) => {
|
const token = await checkTokenIsValid(context, refreshToken)
|
||||||
getTokenDB(context, token, (tokenDB) => {
|
const tokenDB = await getTokenDB(context, token)
|
||||||
getUserFromBody(context, (username, password) =>
|
const { username, password } = await getUserFromBody(context)
|
||||||
getPlayerByIdDB(context, tokenDB, async (player) =>
|
let player = await getPlayerByIdDB(context, tokenDB)
|
||||||
updatePlayerDB(
|
player = await updatePlayerDB(context, player, {
|
||||||
context,
|
username,
|
||||||
player,
|
email: "arst",
|
||||||
{
|
passwordHash: await bcrypt.hash(password, 10),
|
||||||
username,
|
anonymous: false,
|
||||||
email: "arst",
|
})
|
||||||
passwordHash: await bcrypt.hash(password, 10),
|
|
||||||
anonymous: false,
|
return sendResponse(context, {
|
||||||
},
|
message: "Player registered : " + player.id,
|
||||||
(player) => {
|
statusCode: 201,
|
||||||
sendResponse(context, {
|
body: { registered: true },
|
||||||
message: "Player registered : " + player.id,
|
type: ["debug", "infoCyan"],
|
||||||
statusCode: 201,
|
})
|
||||||
body: { registered: true },
|
|
||||||
type: ["debug", "infoCyan"],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).catch((err) => sendError(context, err))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,25 +16,23 @@ export default async function remove(
|
||||||
) {
|
) {
|
||||||
const context = { req, res }
|
const context = { req, res }
|
||||||
|
|
||||||
return getUserFromBody(context, (username, password) =>
|
const { username, password } = await getUserFromBody(context)
|
||||||
getPlayerByNameDB(context, username, (player) => {
|
const player = await getPlayerByNameDB(context, username)
|
||||||
checkPasswordIsValid(context, player, password, () => {
|
await checkPasswordIsValid(context, player, password)
|
||||||
prisma.player.update({
|
prisma.player.update({
|
||||||
where: {
|
where: {
|
||||||
id: player.id,
|
id: player.id,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
deleted: true,
|
deleted: true,
|
||||||
username: null,
|
username: null,
|
||||||
email: null,
|
email: null,
|
||||||
passwordHash: null,
|
passwordHash: null,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
sendResponse(context, {
|
|
||||||
message: "User successfully deleted: " + player.id,
|
return sendResponse(context, {
|
||||||
type: ["debug", "infoCyan"],
|
message: "User successfully deleted: " + player.id,
|
||||||
})
|
type: ["debug", "infoCyan"],
|
||||||
})
|
})
|
||||||
})
|
|
||||||
).catch((err) => sendError(context, err))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ interface SocketData {
|
||||||
|
|
||||||
// const authenticate = (socket, next) => {
|
// const authenticate = (socket, next) => {
|
||||||
// socket.isAuthenticated = false
|
// socket.isAuthenticated = false
|
||||||
// next()
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
async function checkTokenIsValid(rawToken: string) {
|
async function checkTokenIsValid(rawToken: string) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue