feat: admin can answer questions without paying for testing
- Server: /api/respuesta/enviar checks admin cookie; if authorized, bypasses credit check and stores answer via insertAdminAnswer() - DB: insertAdminAnswer() inserts directly into user_answers with username='Admin', skipping the credit budget entirely - Frontend: ProposeAnswer checks /api/admin/status on mount; if admin is logged in, shows the answer form directly (orange Admin badge) instead of the payment tier selection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
30
server.ts
30
server.ts
@@ -7,7 +7,8 @@ import broadcastHtml from "./broadcast.html";
|
||||
import preguntaHtml from "./pregunta.html";
|
||||
import {
|
||||
clearAllRounds, getRounds, getAllRounds,
|
||||
createPendingCredit, activateCredit, getCreditByOrder, submitUserAnswer,
|
||||
createPendingCredit, activateCredit, getCreditByOrder,
|
||||
submitUserAnswer, insertAdminAnswer,
|
||||
getPlayerScores,
|
||||
} from "./db.ts";
|
||||
import { buildPaymentForm, verifyNotification, decodeParams, isPaymentApproved } from "./redsys.ts";
|
||||
@@ -706,7 +707,9 @@ const server = Bun.serve<WsData>({
|
||||
return new Response("Invalid JSON body", { status: 400 });
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
const adminMode = isAdminAuthorized(req, url);
|
||||
|
||||
if (!token && !adminMode) {
|
||||
return new Response("Token requerido", { status: 401 });
|
||||
}
|
||||
if (text.length < 3 || text.length > 150) {
|
||||
@@ -718,17 +721,28 @@ const server = Bun.serve<WsData>({
|
||||
return new Response("No hay ronda activa", { status: 409 });
|
||||
}
|
||||
|
||||
const result = submitUserAnswer(token, round.num, text);
|
||||
if (!result) {
|
||||
return new Response("Crédito no válido o sin respuestas disponibles", { status: 401 });
|
||||
let username: string;
|
||||
let answersLeft: number;
|
||||
|
||||
if (adminMode) {
|
||||
username = "Admin";
|
||||
insertAdminAnswer(round.num, text, username);
|
||||
answersLeft = 999;
|
||||
} else {
|
||||
const result = submitUserAnswer(token, round.num, text);
|
||||
if (!result) {
|
||||
return new Response("Crédito no válido o sin respuestas disponibles", { status: 401 });
|
||||
}
|
||||
username = result.username;
|
||||
answersLeft = result.answersLeft;
|
||||
}
|
||||
|
||||
// Add to live round state and broadcast
|
||||
round.userAnswers = [...(round.userAnswers ?? []), { username: result.username, text }];
|
||||
round.userAnswers = [...(round.userAnswers ?? []), { username, text }];
|
||||
broadcast();
|
||||
|
||||
log("INFO", "respuesta", "User answer submitted", { username: result.username, round: round.num, ip });
|
||||
return new Response(JSON.stringify({ ok: true, answersLeft: result.answersLeft }), {
|
||||
log("INFO", "respuesta", "Answer submitted", { username, round: round.num, admin: adminMode, ip });
|
||||
return new Response(JSON.stringify({ ok: true, answersLeft }), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json", "Cache-Control": "no-store" },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user