fix(api): improve security and performance in leaderboard and rooms
This commit is contained in:
@@ -1,40 +1,53 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "../../../lib/prisma";
|
||||
|
||||
export const revalidate = 60;
|
||||
|
||||
export async function GET() {
|
||||
const users = await prisma.user.findMany({
|
||||
include: { games: true },
|
||||
});
|
||||
try {
|
||||
const users = await prisma.user.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
games: {
|
||||
select: { mode: true, won: true, clicks: true, timeSeconds: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const rows = users
|
||||
.map((u) => {
|
||||
const all = u.games;
|
||||
const solo = all.filter((g) => g.mode === "solo");
|
||||
const multi = all.filter((g) => g.mode === "multi");
|
||||
const wins = all.filter((g) => g.won);
|
||||
const wonGames = all.filter((g) => g.won && g.clicks > 0);
|
||||
const avgClicks = wonGames.length
|
||||
? Math.round(wonGames.reduce((s, g) => s + g.clicks, 0) / wonGames.length)
|
||||
: null;
|
||||
const bestTime = wins.length
|
||||
? Math.min(...wins.map((g) => g.timeSeconds))
|
||||
: null;
|
||||
const rows = users
|
||||
.map((u) => {
|
||||
const all = u.games;
|
||||
const solo = all.filter((g) => g.mode === "solo");
|
||||
const multi = all.filter((g) => g.mode === "multi");
|
||||
const wins = all.filter((g) => g.won);
|
||||
const wonGames = wins.filter((g) => g.clicks > 0);
|
||||
const avgClicks = wonGames.length
|
||||
? Math.round(wonGames.reduce((s, g) => s + g.clicks, 0) / wonGames.length)
|
||||
: null;
|
||||
const bestTime = wins.length
|
||||
? Math.min(...wins.map((g) => g.timeSeconds))
|
||||
: null;
|
||||
|
||||
return {
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
totalGames: all.length,
|
||||
wins: wins.length,
|
||||
soloGames: solo.length,
|
||||
soloWins: solo.filter((g) => g.won).length,
|
||||
multiGames: multi.length,
|
||||
multiWins: multi.filter((g) => g.won).length,
|
||||
avgClicks,
|
||||
bestTime,
|
||||
};
|
||||
})
|
||||
.filter((r) => r.totalGames > 0)
|
||||
.sort((a, b) => b.wins - a.wins || b.totalGames - a.totalGames);
|
||||
return {
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
totalGames: all.length,
|
||||
wins: wins.length,
|
||||
soloGames: solo.length,
|
||||
soloWins: solo.filter((g) => g.won).length,
|
||||
multiGames: multi.length,
|
||||
multiWins: multi.filter((g) => g.won).length,
|
||||
avgClicks,
|
||||
bestTime,
|
||||
};
|
||||
})
|
||||
.filter((r) => r.totalGames > 0)
|
||||
.sort((a, b) => b.wins - a.wins || b.totalGames - a.totalGames)
|
||||
.slice(0, 100);
|
||||
|
||||
return NextResponse.json(rows);
|
||||
return NextResponse.json(rows);
|
||||
} catch {
|
||||
return NextResponse.json({ error: "Erreur serveur" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ function getRooms(): Map<string, Room> {
|
||||
}
|
||||
|
||||
function generatePlayerId(): string {
|
||||
return Math.random().toString(36).slice(2, 10);
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
// Timeout joueur inactif : 15s
|
||||
@@ -156,7 +156,10 @@ export async function PATCH(
|
||||
return Response.json({ error: "Joueur inconnu" }, { status: 404 });
|
||||
}
|
||||
|
||||
player.currentArticle = article ?? "";
|
||||
if (!article || typeof article !== "string" || article.length > 300) {
|
||||
return Response.json({ error: "Article invalide" }, { status: 400 });
|
||||
}
|
||||
player.currentArticle = article;
|
||||
player.lastSeen = Date.now();
|
||||
|
||||
// Verifier si le joueur a atteint la cible
|
||||
@@ -223,3 +226,4 @@ export async function PATCH(
|
||||
return Response.json({ error: "Action inconnue" }, { status: 400 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ function generateCode(): string {
|
||||
}
|
||||
|
||||
function generatePlayerId(): string {
|
||||
return Math.random().toString(36).slice(2, 10);
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
// Nettoie les rooms inactives depuis plus de 2h
|
||||
|
||||
Reference in New Issue
Block a user