Skip to content

Commit ed60da7

Browse files
committed
Added data integrity check
1 parent 9da08c3 commit ed60da7

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/app/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"class-variance-authority": "^0.6.1",
5151
"clsx": "^1.2.1",
5252
"cmdk": "^0.2.0",
53+
"crypto-js": "^4.1.1",
5354
"lucide-react": "^0.259.0",
5455
"next": "13.4.9",
5556
"next-auth": "^4.22.1",

packages/app/src/app/race/_components/race/race-practice.tsx

+14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useRouter } from "next/navigation";
44
import React, { useEffect, useRef, useState } from "react";
55
import { saveUserResultAction } from "../../actions";
6+
import CryptoJS from 'crypto-js';
67

78
// utils
89
import { calculateAccuracy, calculateCPM, noopKeys } from "./utils";
@@ -96,6 +97,17 @@ export default function RacePractice({ user, snippet }: RacePracticeProps) {
9697
},
9798
])
9899
);
100+
101+
const uniqueKey = 'your-unique-key';
102+
const data = {
103+
timeTaken,
104+
errors: totalErrors,
105+
cpm: calculateCPM(code.length - 1, timeTaken),
106+
accuracy: calculateAccuracy(code.length - 1, totalErrors),
107+
snippetId: snippet.id,
108+
};
109+
const jsonData = JSON.stringify(data);
110+
const hashedData = CryptoJS.HmacSHA256(jsonData, uniqueKey).toString();
99111

100112
if (user) {
101113
saveUserResultAction({
@@ -104,6 +116,8 @@ export default function RacePractice({ user, snippet }: RacePracticeProps) {
104116
cpm: calculateCPM(code.length - 1, timeTaken),
105117
accuracy: calculateAccuracy(code.length - 1, totalErrors),
106118
snippetId: snippet.id,
119+
data: jsonData,
120+
hash: hashedData,
107121
})
108122
.then((result) => {
109123
router.push(`/result?resultId=${result.id}`);

packages/app/src/app/race/actions.ts

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { UnauthorizedError } from "@/lib/exceptions/custom-hooks";
66
import { prisma } from "@/lib/prisma";
77
import { getCurrentUser } from "@/lib/session";
88
import { validatedCallback } from "@/lib/validatedCallback";
9+
import CryptoJS from 'crypto-js';
910

1011
export const saveUserResultAction = validatedCallback({
1112
inputValidation: z.object({
@@ -15,6 +16,8 @@ export const saveUserResultAction = validatedCallback({
1516
cpm: z.number(),
1617
accuracy: z.number().min(0).max(100),
1718
snippetId: z.string(),
19+
data: z.string(),
20+
hash: z.string(),
1821
}),
1922
callback: async (input) => {
2023
const user = await getCurrentUser();
@@ -64,6 +67,15 @@ export const saveUserResultAction = validatedCallback({
6467
.sort((a, b) => languagesMap[b] - languagesMap[a])
6568
.splice(0, 3);
6669

70+
// verify hash:
71+
const uniqueKey = 'your-unique-key';
72+
const hashedData = CryptoJS.HmacSHA256(input.data, uniqueKey).toString();
73+
74+
if( hashedData != input.hash.toString() ){
75+
console.log(input.hash.toString(), hashedData);
76+
throw new Error("Invalid Request: Data tampered");
77+
}
78+
6779
return await prisma.$transaction(async (tx) => {
6880
const result = await tx.result.create({
6981
data: {

0 commit comments

Comments
 (0)