From 1efb7c58470746300506c1157efc67dc1ca4e117 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Mon, 17 Jun 2024 02:44:07 +0100 Subject: [PATCH] [Bug] Unauthorized 401 error fix (#2315) * reset scene on 401 * fix: Reset scene and clear session ID on 401 error * Added explanation to clientSessionId --- src/account.ts | 1 + src/phases.ts | 24 +++++++++++++++++++++--- src/system/game-data.ts | 2 +- src/ui/unavailable-modal-ui-handler.ts | 4 ++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/account.ts b/src/account.ts index e5bde56bfe3..4d19513908f 100644 --- a/src/account.ts +++ b/src/account.ts @@ -7,6 +7,7 @@ export interface UserInfo { } export let loggedInUser: UserInfo = null; +// This is a random string that is used to identify the client session - unique per session (tab or window) so that the game will only save on the one that the server is expecting export const clientSessionId = Utils.randomString(32); export function initLoggedInUser(): void { diff --git a/src/phases.ts b/src/phases.ts index ad5819edf30..f4c32284f8c 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -94,7 +94,14 @@ export class LoginPhase extends Phase { this.scene.playSound("menu_open"); const loadData = () => { - updateUserInfo().then(() => this.scene.gameData.loadSystem().then(() => this.end())); + updateUserInfo().then(success => { + if (!success[0]) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); + return; + } + this.scene.gameData.loadSystem().then(() => this.end()); + }); }; this.scene.ui.setMode(Mode.LOGIN_FORM, { @@ -108,7 +115,14 @@ export class LoginPhase extends Phase { buttonActions: [ () => { this.scene.ui.playSelect(); - updateUserInfo().then(() => this.end()); + updateUserInfo().then(success => { + if (!success[0]) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); + return; + } + this.end(); + } ); }, () => { this.scene.unshiftPhase(new LoginPhase(this.scene, false)); this.end(); @@ -118,6 +132,9 @@ export class LoginPhase extends Phase { } ] }); + } else if (statusCode === 401) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); } else { this.scene.unshiftPhase(new UnavailablePhase(this.scene)); super.end(); @@ -4198,7 +4215,8 @@ export class GameOverPhase extends BattlePhase { If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */ if (this.victory) { if (!Utils.isLocal) { - Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true) .then(response => response.json()) + Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true) + .then(response => response.json()) .then(newClear => doGameOver(newClear)); } else { this.scene.gameData.offlineNewClear(this.scene).then(result => { diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 9fb253df092..0e26eab436d 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1261,7 +1261,7 @@ export class GameData { if (!bypassLogin && dataType < GameDataType.SETTINGS) { updateUserInfo().then(success => { - if (!success) { + if (!success[0]) { return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`); } let url: string; diff --git a/src/ui/unavailable-modal-ui-handler.ts b/src/ui/unavailable-modal-ui-handler.ts index 60d01a93c82..cddcde2a1b3 100644 --- a/src/ui/unavailable-modal-ui-handler.ts +++ b/src/ui/unavailable-modal-ui-handler.ts @@ -3,6 +3,7 @@ import { ModalConfig, ModalUiHandler } from "./modal-ui-handler"; import { addTextObject, TextStyle } from "./text"; import { Mode } from "./ui"; import { updateUserInfo } from "#app/account"; +import * as Utils from "#app/utils"; export default class UnavailableModalUiHandler extends ModalUiHandler { private reconnectTimer: NodeJS.Timeout; @@ -55,6 +56,9 @@ export default class UnavailableModalUiHandler extends ModalUiHandler { this.reconnectDuration = this.minTime; this.scene.playSound("pb_bounce_1"); this.reconnectCallback(); + } else if (response[1] === 401) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); } else { this.reconnectDuration = Math.min(this.reconnectDuration * 2, this.maxTime); // Set a max delay so it isn't infinite this.reconnectTimer =