From ab0f5e9837c934e601fe9cd3133a7b2e4e46f474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 6 Jan 2022 10:49:44 +0100 Subject: [PATCH 1/4] Stopping sending literal errors Errors now must be of "Error" type. Rule added in eslint. --- back/.eslintrc.json | 3 ++- front/.eslintrc.js | 1 + front/src/Components/Menu/AudioGlobalMessage.svelte | 2 +- front/src/Components/Menu/Menu.svelte | 2 +- front/src/Connexion/ConnectionManager.ts | 8 ++++---- front/src/Connexion/RoomConnection.ts | 2 +- front/src/Phaser/Entity/PlayerTexturesLoadingManager.ts | 2 +- front/src/Phaser/Game/GameManager.ts | 6 +++--- front/src/Phaser/Game/GameScene.ts | 2 +- front/src/Phaser/Login/CustomizeScene.ts | 2 +- front/src/Stores/ChatStore.ts | 2 +- front/src/WebRtc/ColorGenerator.ts | 2 +- front/src/WebRtc/DeviceUtils.ts | 2 +- front/src/WebRtc/SimplePeer.ts | 6 +++--- pusher/.eslintrc.json | 3 ++- pusher/src/Controller/AdminController.ts | 8 ++++---- pusher/src/Controller/AuthenticateController.ts | 2 +- pusher/src/Controller/OpenIdProfileController.ts | 2 +- pusher/src/Services/SocketManager.ts | 2 +- 19 files changed, 31 insertions(+), 28 deletions(-) diff --git a/back/.eslintrc.json b/back/.eslintrc.json index 3aab37d9..ce78dd63 100644 --- a/back/.eslintrc.json +++ b/back/.eslintrc.json @@ -25,6 +25,7 @@ ], "rules": { "no-unused-vars": "off", - "@typescript-eslint/no-explicit-any": "error" + "@typescript-eslint/no-explicit-any": "error", + "no-throw-literal": "error" } } diff --git a/front/.eslintrc.js b/front/.eslintrc.js index dc2b6bd6..ed94b3b2 100644 --- a/front/.eslintrc.js +++ b/front/.eslintrc.js @@ -34,6 +34,7 @@ module.exports = { "rules": { "no-unused-vars": "off", "@typescript-eslint/no-explicit-any": "error", + "no-throw-literal": "error", // TODO: remove those ignored rules and write a stronger code! "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/restrict-plus-operands": "off", diff --git a/front/src/Components/Menu/AudioGlobalMessage.svelte b/front/src/Components/Menu/AudioGlobalMessage.svelte index d8f3c932..51caee17 100644 --- a/front/src/Components/Menu/AudioGlobalMessage.svelte +++ b/front/src/Components/Menu/AudioGlobalMessage.svelte @@ -26,7 +26,7 @@ const selectedFile = inputAudio.files ? inputAudio.files[0] : null; if (!selectedFile) { errorFile = true; - throw "no file selected"; + throw new Error("no file selected"); } const fd = new FormData(); diff --git a/front/src/Components/Menu/Menu.svelte b/front/src/Components/Menu/Menu.svelte index 84f78d32..b02df36d 100644 --- a/front/src/Components/Menu/Menu.svelte +++ b/front/src/Components/Menu/Menu.svelte @@ -76,7 +76,7 @@ break; } } - } else throw "There is no menu called " + menu; + } else throw new Error("There is no menu called " + menu); } function closeMenu() { diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index 9c81fb25..e520faed 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -106,10 +106,10 @@ class ConnectionManager { const code = urlParams.get("code"); const state = urlParams.get("state"); if (!state || !localUserStore.verifyState(state)) { - throw "Could not validate state!"; + throw new Error("Could not validate state!"); } if (!code) { - throw "No Auth code provided"; + throw new Error("No Auth code provided"); } localUserStore.setCode(code); } @@ -333,10 +333,10 @@ class ConnectionManager { if (!token) { if (!state || !localUserStore.verifyState(state)) { - throw "Could not validate state!"; + throw new Error("Could not validate state!"); } if (!code) { - throw "No Auth code provided"; + throw new Error("No Auth code provided"); } } const { authToken, userUuid, textures, email } = await Axios.get(`${PUSHER_URL}/login-callback`, { diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index d360c705..4e2f8397 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -691,7 +691,7 @@ export class RoomConnection implements RoomConnection { } public getUserId(): number { - if (this.userId === null) throw "UserId cannot be null!"; + if (this.userId === null) throw new Error("UserId cannot be null!"); return this.userId; } diff --git a/front/src/Phaser/Entity/PlayerTexturesLoadingManager.ts b/front/src/Phaser/Entity/PlayerTexturesLoadingManager.ts index edaeb5b8..58fcf84c 100644 --- a/front/src/Phaser/Entity/PlayerTexturesLoadingManager.ts +++ b/front/src/Phaser/Entity/PlayerTexturesLoadingManager.ts @@ -90,7 +90,7 @@ export const getRessourceDescriptor = ( const playerResource = LAYERS[i][textureName]; if (playerResource !== undefined) return playerResource; } - throw "Could not find a data for texture " + textureName; + throw new Error("Could not find a data for texture " + textureName); }; export const createLoadingPromise = ( diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index 04db08a3..e4f4ea1c 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -66,7 +66,7 @@ export class GameManager { getCharacterLayers(): string[] { if (!this.characterLayers) { - throw "characterLayers are not set"; + throw new Error("characterLayers are not set"); } return this.characterLayers; } @@ -119,7 +119,7 @@ export class GameManager { * This will close the socket connections and stop the gameScene, but won't remove it. */ leaveGame(targetSceneName: string, sceneClass: Phaser.Scene): void { - if (this.currentGameSceneName === null) throw "No current scene id set!"; + if (this.currentGameSceneName === null) throw new Error("No current scene id set!"); const gameScene: GameScene = this.scenePlugin.get(this.currentGameSceneName) as GameScene; gameScene.cleanupClosingScene(); gameScene.createSuccessorGameScene(false, false); @@ -143,7 +143,7 @@ export class GameManager { } public getCurrentGameScene(): GameScene { - if (this.currentGameSceneName === null) throw "No current scene id set!"; + if (this.currentGameSceneName === null) throw new Error("No current scene id set!"); return this.scenePlugin.get(this.currentGameSceneName) as GameScene; } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index b6d7274c..740de4c1 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -453,7 +453,7 @@ export class GameScene extends DirtyScene { const playerName = gameManager.getPlayerName(); if (!playerName) { - throw "playerName is not set"; + throw new Error("playerName is not set"); } this.playerName = playerName; this.characterLayers = gameManager.getCharacterLayers(); diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts index 5c208edd..42312eab 100644 --- a/front/src/Phaser/Login/CustomizeScene.ts +++ b/front/src/Phaser/Login/CustomizeScene.ts @@ -48,7 +48,7 @@ export class CustomizeScene extends AbstractCharacterScene { bodyResourceDescription.level < 0 || bodyResourceDescription.level > 5 ) { - throw "Texture level is null"; + throw new Error("Texture level is null"); } this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription); }); diff --git a/front/src/Stores/ChatStore.ts b/front/src/Stores/ChatStore.ts index 3b097a9a..7e6375e5 100644 --- a/front/src/Stores/ChatStore.ts +++ b/front/src/Stores/ChatStore.ts @@ -26,7 +26,7 @@ export interface ChatMessage { function getAuthor(authorId: number): PlayerInterface { const author = playersStore.getPlayerById(authorId); if (!author) { - throw "Could not find data for author " + authorId; + throw new Error("Could not find data for author " + authorId); } return author; } diff --git a/front/src/WebRtc/ColorGenerator.ts b/front/src/WebRtc/ColorGenerator.ts index f78671e6..971715a6 100644 --- a/front/src/WebRtc/ColorGenerator.ts +++ b/front/src/WebRtc/ColorGenerator.ts @@ -62,7 +62,7 @@ function hsv_to_rgb(hue: number, saturation: number, brightness: number): { r: n b = q; break; default: - throw "h_i cannot be " + h_i; + throw new Error("h_i cannot be " + h_i); } return { r, diff --git a/front/src/WebRtc/DeviceUtils.ts b/front/src/WebRtc/DeviceUtils.ts index 9be07501..73dc5236 100644 --- a/front/src/WebRtc/DeviceUtils.ts +++ b/front/src/WebRtc/DeviceUtils.ts @@ -22,7 +22,7 @@ export function getNavigatorType(): NavigatorType { } else if (window.navigator.userAgent.includes("Safari")) { return NavigatorType.safari; } - throw "Couldn't detect navigator type"; + throw new Error("Couldn't detect navigator type"); } export function isAndroid(): boolean { return window.navigator.userAgent.includes("Android"); diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index f4016015..b0ba84e3 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -123,7 +123,7 @@ export class SimplePeer { peerConnection.destroy(); const peerConnexionDeleted = this.PeerConnectionArray.delete(user.userId); if (!peerConnexionDeleted) { - throw "Error to delete peer connection"; + throw new Error("Error to delete peer connection"); } //return this.createPeerConnection(user, localStream); } else { @@ -177,7 +177,7 @@ export class SimplePeer { peerConnection.destroy(); const peerConnexionDeleted = this.PeerScreenSharingConnectionArray.delete(user.userId); if (!peerConnexionDeleted) { - throw "Error to delete peer connection"; + throw new Error("Error to delete peer connection"); } this.createPeerConnection(user); } else { @@ -229,7 +229,7 @@ export class SimplePeer { const userIndex = this.Users.findIndex((user) => user.userId === userId); if (userIndex < 0) { - throw "Couldn't delete user"; + throw new Error("Couldn't delete user"); } else { this.Users.splice(userIndex, 1); } diff --git a/pusher/.eslintrc.json b/pusher/.eslintrc.json index 3aab37d9..ce78dd63 100644 --- a/pusher/.eslintrc.json +++ b/pusher/.eslintrc.json @@ -25,6 +25,7 @@ ], "rules": { "no-unused-vars": "off", - "@typescript-eslint/no-explicit-any": "error" + "@typescript-eslint/no-explicit-any": "error", + "no-throw-literal": "error" } } diff --git a/pusher/src/Controller/AdminController.ts b/pusher/src/Controller/AdminController.ts index bf514fa0..85116df9 100644 --- a/pusher/src/Controller/AdminController.ts +++ b/pusher/src/Controller/AdminController.ts @@ -39,7 +39,7 @@ export class AdminController extends BaseController { try { if (typeof body.roomId !== "string") { - throw "Incorrect roomId parameter"; + throw new Error("Incorrect roomId parameter"); } const roomId: string = body.roomId; @@ -86,13 +86,13 @@ export class AdminController extends BaseController { try { if (typeof body.text !== "string") { - throw "Incorrect text parameter"; + throw new Error("Incorrect text parameter"); } if (body.type !== "capacity" && body.type !== "message") { - throw "Incorrect type parameter"; + throw new Error("Incorrect type parameter"); } if (!body.targets || typeof body.targets !== "object") { - throw "Incorrect targets parameter"; + throw new Error("Incorrect targets parameter"); } const text: string = body.text; const type: string = body.type; diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index 149253b3..fe80eafa 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -32,7 +32,7 @@ export class AuthenticateController extends BaseController { try { const { nonce, state, playUri, redirect } = parse(req.getQuery()); if (!state || !nonce) { - throw "missing state and nonce URL parameters"; + throw new Error("missing state and nonce URL parameters"); } const loginUri = await openIDClient.authorizationUrl( diff --git a/pusher/src/Controller/OpenIdProfileController.ts b/pusher/src/Controller/OpenIdProfileController.ts index f33e7a22..8c7b4a4b 100644 --- a/pusher/src/Controller/OpenIdProfileController.ts +++ b/pusher/src/Controller/OpenIdProfileController.ts @@ -27,7 +27,7 @@ export class OpenIdProfileController extends BaseController { try { const resCheckTokenAuth = await openIDClient.checkTokenAuth(accessToken as string); if (!resCheckTokenAuth.email) { - throw "Email was not found"; + throw new Error("Email was not found"); } res.end( this.buildHtml( diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 43e85b88..30fe761f 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -671,7 +671,7 @@ export class SocketManager implements ZoneEventListener { playGlobalMessageEvent: PlayGlobalMessage ): Promise { if (!client.tags.includes("admin")) { - throw "Client is not an admin!"; + throw new Error("Client is not an admin!"); } const clientRoomUrl = client.roomId; From d713c82568a096bc384d2d4f4e5f46fe662f4612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 6 Jan 2022 11:46:07 +0100 Subject: [PATCH 2/4] Fixing WA crashing in Firefox private mode Due to the way we now handle the browser cache, previously ignored errors in the Cache API were now explicitly thrown, preventing the loading of Firefox in private mode. This commit fixes the issue and improves the stacktrace display of errors at the same time. --- front/src/Connexion/ConnectionManager.ts | 3 +++ front/src/Connexion/LocalUserStore.ts | 10 +++++++--- front/src/Phaser/Reconnecting/ErrorScene.ts | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index 9c81fb25..5fe3d029 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -168,6 +168,9 @@ class ConnectionManager { } } catch (err) { console.error(err); + if (err instanceof Error) { + console.error(err.stack); + } } } else { const query = urlParams.toString(); diff --git a/front/src/Connexion/LocalUserStore.ts b/front/src/Connexion/LocalUserStore.ts index cc84f043..24d4ab42 100644 --- a/front/src/Connexion/LocalUserStore.ts +++ b/front/src/Connexion/LocalUserStore.ts @@ -139,9 +139,13 @@ class LocalUserStore { async setLastRoomUrl(roomUrl: string): Promise { localStorage.setItem(lastRoomUrl, roomUrl.toString()); if ("caches" in window) { - const cache = await caches.open(cacheAPIIndex); - const stringResponse = new Response(JSON.stringify({ roomUrl })); - await cache.put(`/${lastRoomUrl}`, stringResponse); + try { + const cache = await caches.open(cacheAPIIndex); + const stringResponse = new Response(JSON.stringify({ roomUrl })); + await cache.put(`/${lastRoomUrl}`, stringResponse); + } catch (e) { + console.error("Could not store last room url in Browser cache. Are you using private browser mode?", e); + } } } getLastRoomUrl(): string { diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts index 078bee71..ea593c45 100644 --- a/front/src/Phaser/Reconnecting/ErrorScene.ts +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -78,6 +78,9 @@ export class ErrorScene extends Phaser.Scene { */ public static showError(error: unknown, scene: ScenePlugin): void { console.error(error); + if (error instanceof Error) { + console.error("Stacktrace: ", error.stack); + } console.trace(); if (typeof error === "string" || error instanceof String) { From 0fb09cc431474ac00fc9fe5e69e7a8122b479380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 6 Jan 2022 12:27:00 +0100 Subject: [PATCH 3/4] Fixing closing of all websites. --- front/src/WebRtc/CoWebsiteManager.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index 8bff2acb..48cc9680 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -612,17 +612,16 @@ class CoWebsiteManager { } } - public closeCoWebsites(): Promise { - this.currentOperationPromise = this.currentOperationPromise.then(() => { - const promises: Promise[] = []; - this.coWebsites.forEach((coWebsite: CoWebsite) => { - promises.push(this.closeCoWebsite(coWebsite)); - }); - return Promise.all(promises).then(() => { - return; - }); + public async closeCoWebsites(): Promise { + await this.currentOperationPromise; + + const promises: Promise[] = []; + this.coWebsites.forEach((coWebsite: CoWebsite) => { + promises.push(this.closeCoWebsite(coWebsite)); }); - return this.currentOperationPromise; + await Promise.all(promises); + // TODO: this.currentOperationPromise does not point any more on the last promise + return; } public getGameSize(): { width: number; height: number } { From 2f4e518f17099298bf49b601757133718278bc6a Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Wed, 12 Jan 2022 08:20:54 +0100 Subject: [PATCH 4/4] HotFix Htaccess to accespt "*" Signed-off-by: Gregoire Parant --- front/dist/.htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/dist/.htaccess b/front/dist/.htaccess index b3bdfa2d..92ea1eec 100644 --- a/front/dist/.htaccess +++ b/front/dist/.htaccess @@ -20,7 +20,7 @@ RewriteBase / # We only want to let Apache serve files and not directories. # Rewrite all other queries starting with _ to index.ts. RewriteCond %{REQUEST_FILENAME} !-f -RewriteRule "^[_@]/" "/index.html" [L] +RewriteRule "^[_@*]/" "/index.html" [L] RewriteRule "^register/" "/index.html" [L] RewriteRule "^login" "/index.html" [L] RewriteRule "^jwt" "/index.html" [L]