diff --git a/backend/src/anticheat/index.ts b/backend/src/anticheat/index.ts index 4e3063dbf..51f17d15c 100644 --- a/backend/src/anticheat/index.ts +++ b/backend/src/anticheat/index.ts @@ -5,7 +5,8 @@ export function implemented(): boolean { export function validateResult( _result: object, _version: string, - _uaStringifiedObject: string + _uaStringifiedObject: string, + _lbOptOut: boolean ): boolean { return true; } diff --git a/backend/src/api/controllers/result.ts b/backend/src/api/controllers/result.ts index 937ad666f..6c8a4f1d5 100644 --- a/backend/src/api/controllers/result.ts +++ b/backend/src/api/controllers/result.ts @@ -202,7 +202,8 @@ export async function addResult( !validateResult( result, req.headers["client-version"] as string, - JSON.stringify(new UAParser(req.headers["user-agent"]).getResult()) + JSON.stringify(new UAParser(req.headers["user-agent"]).getResult()), + user.lbOptOut === true ) ) { const status = MonkeyStatusCodes.RESULT_DATA_INVALID; diff --git a/backend/src/api/controllers/user.ts b/backend/src/api/controllers/user.ts index 7de823537..525836f4d 100644 --- a/backend/src/api/controllers/user.ts +++ b/backend/src/api/controllers/user.ts @@ -63,7 +63,19 @@ export async function sendVerificationEmail( req: MonkeyTypes.Request ): Promise { const { email, uid } = req.ctx.decodedToken; - const isVerified = (await admin.auth().getUser(uid)).emailVerified; + const isVerified = ( + await admin + .auth() + .getUser("uid") + .catch((e) => { + throw new MonkeyError( + 500, // this should never happen, but it does. it mightve been caused by auth token cache, will see if disabling cache fixes it + "Auth user not found, even though the token got decoded", + JSON.stringify({ uid, email, stack: e.stack }), + uid + ); + }) + ).emailVerified; if (isVerified === true) { throw new MonkeyError(400, "Email already verified"); } diff --git a/backend/src/api/routes/users.ts b/backend/src/api/routes/users.ts index 790e05b55..2ba351d23 100644 --- a/backend/src/api/routes/users.ts +++ b/backend/src/api/routes/users.ts @@ -593,7 +593,9 @@ router.post( router.get( "/verificationEmail", - authenticateRequest(), + authenticateRequest({ + noCache: true, + }), RateLimit.userRequestVerificationEmail, asyncHandler(UserController.sendVerificationEmail) ); diff --git a/frontend/src/ts/controllers/input-controller.ts b/frontend/src/ts/controllers/input-controller.ts index 1e0624281..0add51422 100644 --- a/frontend/src/ts/controllers/input-controller.ts +++ b/frontend/src/ts/controllers/input-controller.ts @@ -761,6 +761,8 @@ function handleTab(event: JQuery.KeyDownEvent, popupVisible: boolean): void { } } +let lastBailoutAttempt = -1; + $(document).keydown(async (event) => { if (ActivePage.get() == "loading") return; @@ -874,8 +876,23 @@ $(document).keydown(async (event) => { CustomTextState.isCustomTextLong() ?? false ) ) { - TestInput.setBailout(true); - TestLogic.finish(); + const delay = Date.now() - lastBailoutAttempt; + if (lastBailoutAttempt === -1 || delay > 200) { + lastBailoutAttempt = Date.now(); + if (delay >= 5000) { + Notifications.add( + "Please double tap shift+enter to confirm bail out", + 0, + { + important: true, + duration: 5000, + } + ); + } + } else { + TestInput.setBailout(true); + TestLogic.finish(); + } } } else { handleChar("\n", TestInput.input.current.length); diff --git a/frontend/static/quotes/english.json b/frontend/static/quotes/english.json index b00c88910..fc247cef5 100644 --- a/frontend/static/quotes/english.json +++ b/frontend/static/quotes/english.json @@ -38966,6 +38966,24 @@ "source": "Clockwork Princess", "length": 66, "id": 6854 + }, + { + "text": "Love cannot be explained. It can only be experienced. Love cannot be explained, yet it explains all.", + "source": "The Forty Rules of Love", + "length": 100, + "id": 6855 + }, + { + "text": "If we are the same person before and after we loved, that means we haven't loved enough.", + "source": "The Forty Rules of Love", + "length": 88, + "id": 6856 + }, + { + "text": "Even if a single day in your life is the same as the day before, it surely is a pity. At every moment and with each new breath, one should be renewed and renewed again. There is only one way to be born into a new life: to die before death.", + "source": "The Forty Rules of Love", + "length": 239, + "id": 6857 } ] }