diff --git a/backend/api/controllers/result.js b/backend/api/controllers/result.js index 2405bc045..30b1c4a11 100644 --- a/backend/api/controllers/result.js +++ b/backend/api/controllers/result.js @@ -7,6 +7,7 @@ const { validateResult, } = require("../../handlers/validation"); const { stdDev, roundTo2 } = require("../../handlers/misc"); +const objecthash = require("object-hash"); class ResultController { static async getResults(req, res, next) { @@ -92,6 +93,21 @@ class ResultController { .json({ message: "Result data doesn't make sense" }); } + let resulthash = result.hash; + delete result.hash; + const serverhash = objecthash(result); + if (serverhash !== resulthash) { + return res.status(400).json({ message: "Incorrect result hash" }); + } + + let timestampres = await ResultDAO.getResultByTimestamp( + uid, + result.timestamp + ); + if (timestampres) { + return res.status(400).json({ message: "Duplicate result" }); + } + try { result.keySpacingStats = { average: diff --git a/backend/dao/result.js b/backend/dao/result.js index ca79b5161..cf60d245a 100644 --- a/backend/dao/result.js +++ b/backend/dao/result.js @@ -47,6 +47,10 @@ class ResultDAO { return result; } + static async getResultByTimestamp(uid, timestamp) { + return await mongoDB().collection("results").findOne({ uid, timestamp }); + } + static async getResults(uid, start, end) { start = start ?? 0; end = end ?? 1000; diff --git a/src/js/test/test-logic.js b/src/js/test/test-logic.js index 925a67299..6807b0429 100644 --- a/src/js/test/test-logic.js +++ b/src/js/test/test-logic.js @@ -37,6 +37,8 @@ import * as Wordset from "./wordset"; import * as ChallengeContoller from "./challenge-controller"; import * as RateQuotePopup from "./rate-quote-popup"; +const objecthash = require("object-hash"); + let glarsesMode = false; export function toggleGlarses() { @@ -1781,6 +1783,9 @@ export async function finish(difficultyFailed = false) { completedEvent.challenge = ChallengeContoller.verify( completedEvent ); + console.time("hash"); + completedEvent.hash = objecthash(completedEvent); + console.timeEnd("hash"); axiosInstance .post("/results/add", { result: completedEvent,