From 748baa9bbcd1d7366b71e56924b63e56faf4e8ef Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 10:23:36 +0200 Subject: [PATCH 01/39] Refactoring Error Screen --- front/src/Components/App.svelte | 9 +- front/src/Components/UI/ErrorScreen.svelte | 158 ++++++++++++++++++ front/src/Components/images/button-large.png | Bin 0 -> 3571 bytes front/src/Components/images/cup.png | Bin 0 -> 1729 bytes front/src/Components/images/error.png | Bin 0 -> 4800 bytes front/src/Components/images/external-link.png | Bin 0 -> 10701 bytes .../src/Components/images/logo-min-white.png | Bin 0 -> 7558 bytes front/src/Components/images/reload.png | Bin 0 -> 3660 bytes front/src/Connexion/RoomConnection.ts | 13 ++ front/src/Phaser/Login/EntryScene.ts | 36 ++-- front/src/Phaser/Reconnecting/ErrorScene.ts | 7 - front/src/Phaser/Reconnecting/WAError.ts | 45 ++++- front/src/Stores/ErrorScreenStore.ts | 18 ++ messages/protos/messages.proto | 13 ++ .../src/Controller/AuthenticateController.ts | 2 + pusher/src/Controller/BaseHttpController.ts | 14 +- pusher/src/Controller/IoSocketController.ts | 22 ++- pusher/src/Services/AdminApi.ts | 17 +- pusher/src/Services/SocketManager.ts | 22 ++- 19 files changed, 315 insertions(+), 61 deletions(-) create mode 100644 front/src/Components/UI/ErrorScreen.svelte create mode 100644 front/src/Components/images/button-large.png create mode 100644 front/src/Components/images/cup.png create mode 100644 front/src/Components/images/error.png create mode 100644 front/src/Components/images/external-link.png create mode 100644 front/src/Components/images/logo-min-white.png create mode 100644 front/src/Components/images/reload.png create mode 100644 front/src/Stores/ErrorScreenStore.ts diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index c596c8ee..3405aa71 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -2,6 +2,7 @@ import type { Game } from "../Phaser/Game/Game"; import { chatVisibilityStore } from "../Stores/ChatStore"; import { errorStore } from "../Stores/ErrorStore"; + import { errorScreenStore } from "../Stores/ErrorScreenStore"; import { loginSceneVisibleStore } from "../Stores/LoginSceneStore"; import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; @@ -13,11 +14,17 @@ import SelectCharacterScene from "./selectCharacter/SelectCharacterScene.svelte"; import SelectCompanionScene from "./SelectCompanion/SelectCompanionScene.svelte"; import ErrorDialog from "./UI/ErrorDialog.svelte"; + import ErrorScreen from "./UI/ErrorScreen.svelte"; + export let game: Game; -{#if $errorStore.length > 0} +{#if $errorScreenStore !== undefined} +
+ +
+{:else if $errorStore.length > 0}
diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte new file mode 100644 index 00000000..276484b1 --- /dev/null +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -0,0 +1,158 @@ + + +
+
+ +
+ {#if $errorScreenStore.type !== 'retry'}

{$errorScreenStore.title}

{/if} +

{$errorScreenStore.subtitle}

+ {#if $errorScreenStore.type !== 'retry'}

Code : {$errorScreenStore.code}

{/if} +

{detailsStylized}{#if $errorScreenStore.type === 'retry'}

{/if}

+ {#if ($errorScreenStore.type === 'retry' && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === 'redirect' && (window.history.length > 2 || $errorScreenStore.urlToRedirect))} +
+ + {$errorScreenStore.buttonTitle} +
+ {/if} +
+ +
+ + diff --git a/front/src/Components/images/button-large.png b/front/src/Components/images/button-large.png new file mode 100644 index 0000000000000000000000000000000000000000..f1d52f50d0867a135f1003aec89f56343d2086ec GIT binary patch literal 3571 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 literal 0 HcmV?d00001 diff --git a/front/src/Components/images/cup.png b/front/src/Components/images/cup.png new file mode 100644 index 0000000000000000000000000000000000000000..2f0e15c324e66cb6fb29113f9e71c80da97ef816 GIT binary patch literal 1729 zcmai#X;cze6vt_D)GT!>bIh&H%9&gzYs?(c(v)$}@_6=_Sf8~6qQU~%BT*cA5{Fctt%y#aD|Iu}Qr<2XeQ zp8=fV@;RDuFeDnTQ-OrI9b?JR^28TQ@f(J zeOswQuc94K4*1GP>&=cZ-O%dy7vshshlH(|URmXQ0n6>`SYv1N*l&Qc0+rf!218; zy*!qV+^y1*v&X2nf=gJ26&IPL097!gBsFxC(FR#L-TaaSu*j|%p98QgiT zBy1|k1DWh%H1CaqE{tvMNQ1n#(7yg4fQ?NMIb(hFP>iR>guXl5q!A$RB$CqCKN_4 zGm4q>?h-K}Qo4GwrBKUcyTccj7rQSk_4Sr`!|JQO4`n=yq|GfXESxu_dqUs>>csCh z@qP#hm5vahD6z8m-uZCVdo3@UBTxcgHN5(sFT~fE`RTZjwpUK~smZP6n?QJzY_F2_ zI;5*iCcBrLn;SfMj3q+<)ZSEnGh&`vt(BC^6115YVB{hJs}jv^7)nBGK$=W*UF;hZ5JAf?5O%UzfNa#vG*A>4ZGq$SZE>^7;Fz&ihSj!Abc(+r zz5muaxeJBtyJJF4*#O~ajn0=ocBr|`fR2RlhJV8B`ja!!dd-f4=fv22kX!xdu96*mN@hV=|RvA zFl^RheV0lLh~r`$vp02N-v%Z;Y!Ptyk{ym;&uAx;$*Daym1~6yhn@=7!X6+4MHG)G zm)s@qFNT2SMv6BgM=C1a3`*4gLdA@|BYUV+7zl=Gv)6DLCX00bV$X@Wj~_b~PH|xb zKuEbec|b=91sy@M5dKOCp6(-y+FeRFWT!d90&gl3fXJ8V^T}w3FpFr2e(%79OGX~rtPaJee zxTvJMzl@n}T`XK}nMuE$S6*VB$EwB_xCJ!9S$e(Kkll~%S?e9O;nPFVr-E{?Alrx& zmHvW&hVgzBj7Sc=S5=3%_+`Q$MAD^rGVq>dmL54?C6#FH?~?QD>r(C7m1?RSD)Kk_ zo4n-6sx=d13gU_v^2tM*gGFWxZ}t#)K)i-K=)NV5k?mPvTE>oE z4H~U45HkKinvxTT`UbN-51)K%E@g4_pz_VpP}=;go@tokPXd5kyqv2}1>OA@0FrOa literal 0 HcmV?d00001 diff --git a/front/src/Components/images/error.png b/front/src/Components/images/error.png new file mode 100644 index 0000000000000000000000000000000000000000..a0fbc29b0a45a7c7a6f499a828a3ac052160449c GIT binary patch literal 4800 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%0DjG6@d(~DG;N#*SSWrBa@|J(9yE@;+A^FY? ze9V$boF2Iwy<)FaAR<35CkXZfXh}uUZV;MhBwcX=bL5E$SJ#fCVC;&l zcFf{06lGv|cjQb@G!sM2+1KXL%s}%Q{@8z-};zHi3t<{#S{qQ7joR#jyAKy2={sQoc~3=dYZ81QZUUbjuBAUo~Zo@-Ub z77xTK#Xx1zXrVM(CIeH!Xq7aY7iduwG)=x}abtBONFy zc)9|XQ4993WtMqy?fJ6hM-r+|ke& zO$?)Xfoes;hV(R^BQoe)pm2B8B7CpS!1TzGn!?=RKO51z_!{?Adn{|H$42z0ClHAWa3cYubr z2OIa`t?K;4g{PvjCB=b`YltrSxQfAG^Y^-0Gu?v=PMnTkhWeBZ{}uz%NQe&&7J=A)xDz#ts$wt!OkXemEh%F`q-?2zDP z*k^P8%xq1ICx3^GrC>@)ZQ3vb%8=*wA>rc62N&};#-=l;7z*I0g6*8I^Xi^kRpIK=v0}5O77q0>>)6(o14?T^H*k9Hd3KH~m L^>bP0l+XkKddGK2 literal 0 HcmV?d00001 diff --git a/front/src/Components/images/logo-min-white.png b/front/src/Components/images/logo-min-white.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5796b08ce5f3f9a8f630d21cce0e687eba10d0 GIT binary patch literal 7558 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 G_`d)$Xcq(); public readonly errorMessageStream = this._errorMessageStream.asObservable(); + private readonly _errorV2MessageStream = new Subject(); + public readonly errorV2MessageStream = this._errorV2MessageStream.asObservable(); + private readonly _roomJoinedMessageStream = new Subject<{ connection: RoomConnection; room: RoomJoinedMessageInterface; @@ -475,6 +481,13 @@ export class RoomConnection implements RoomConnection { console.error("An error occurred server side: " + message.errorMessage.message); break; } + case "errorV2Message": { + this._errorV2MessageStream.next(message.errorV2Message); + if(message.errorV2Message.code !== 'retry') this.closed = true; + console.error("An error occurred server side: " + message.errorV2Message.code); + errorScreenStore.setError(message.errorV2Message as unknown as WAError); + break; + } default: { // Security check: if we forget a "case", the line below will catch the error at compile-time. const tmp: never = message; diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 41910f26..42c9f617 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -4,9 +4,8 @@ import { ErrorScene } from "../Reconnecting/ErrorScene"; import { WAError } from "../Reconnecting/WAError"; import { waScaleManager } from "../Services/WaScaleManager"; import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene"; -import LL from "../../i18n/i18n-svelte"; -import { get } from "svelte/store"; import { localeDetector } from "../../i18n/locales"; +import {errorScreenStore} from "../../Stores/ErrorScreenStore"; export const EntrySceneName = "EntryScene"; @@ -47,27 +46,18 @@ export class EntryScene extends Scene { this.scene.start(nextSceneName); }) .catch((err) => { - const $LL = get(LL); - if (err.response && err.response.status == 404) { - ErrorScene.showError( - new WAError( - $LL.error.accessLink.title(), - $LL.error.accessLink.subTitle(), - $LL.error.accessLink.details() - ), - this.scene - ); - } else if (err.response && err.response.status == 403) { - ErrorScene.showError( - new WAError( - $LL.error.connectionRejected.title(), - $LL.error.connectionRejected.subTitle({ - error: err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "", - }), - $LL.error.connectionRejected.details() - ), - this.scene - ); + if (err.response.data?.code) { + errorScreenStore.setError(new WAError( + err.response.data.type, + err.response.data.code, + err.response.data.title, + err.response.data.subtitle, + err.response.data.details, + err.response.data.timeToRetry, + err.response.data.canRetryManual, + err.response.data.urlToRedirect, + err.response.data.buttonTitle + )); } else { ErrorScene.showError(err, this.scene); } diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts index ea593c45..2e86983e 100644 --- a/front/src/Phaser/Reconnecting/ErrorScene.ts +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -3,7 +3,6 @@ import Image = Phaser.GameObjects.Image; import Sprite = Phaser.GameObjects.Sprite; import Text = Phaser.GameObjects.Text; import ScenePlugin = Phaser.Scenes.ScenePlugin; -import { WAError } from "./WAError"; import Axios from "axios"; export const ErrorSceneName = "ErrorScene"; @@ -88,12 +87,6 @@ export class ErrorScene extends Phaser.Scene { title: "An error occurred", subTitle: error, }); - } else if (error instanceof WAError) { - scene.start(ErrorSceneName, { - title: error.title, - subTitle: error.subTitle, - message: error.details, - }); } else if (Axios.isAxiosError(error) && error.response) { // Axios HTTP error // client received an error response (5xx, 4xx) diff --git a/front/src/Phaser/Reconnecting/WAError.ts b/front/src/Phaser/Reconnecting/WAError.ts index abc71f6c..84bc95ed 100644 --- a/front/src/Phaser/Reconnecting/WAError.ts +++ b/front/src/Phaser/Reconnecting/WAError.ts @@ -1,26 +1,55 @@ export class WAError extends Error { + private _type: string; + private _code: string; private _title: string; - private _subTitle: string; + private _subtitle: string; private _details: string; + private _timeToRetry:number; + private _canRetryManual: boolean; + private _urlToRedirect: string; + private _buttonTitle: string; - constructor(title: string, subTitle: string, details: string) { - super(title + " - " + subTitle + " - " + details); + constructor(type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + super(title + " - " + subtitle + " - " + details); + + this._type = type; + this._code = code; this._title = title; - this._subTitle = subTitle; + this._subtitle = subtitle; this._details = details; + this._timeToRetry = timeToRetry; + this._canRetryManual = canRetryManual; + this._urlToRedirect = urlToRedirect; + this._buttonTitle = buttonTitle; // Set the prototype explicitly. Object.setPrototypeOf(this, WAError.prototype); } + get type(): string { + return this._type; + } + get code(): string { + return this._code; + } get title(): string { return this._title; } - - get subTitle(): string { - return this._subTitle; + get subtitle(): string { + return this._subtitle; } - get details(): string { return this._details; } + get timeToRetry(): number { + return this._timeToRetry; + } + get buttonTitle(): string { + return this._buttonTitle; + } + get urlToRedirect(): string { + return this._urlToRedirect; + } + get canRetryManual(): boolean { + return this._canRetryManual; + } } diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts new file mode 100644 index 00000000..dc31b1cf --- /dev/null +++ b/front/src/Stores/ErrorScreenStore.ts @@ -0,0 +1,18 @@ +import {writable} from "svelte/store"; +import {WAError} from "../Phaser/Reconnecting/WAError"; + +/** + * A store that contains one error of type WAError to be displayed. + */ +function createErrorScreenStore() { + const { subscribe, set } = writable(undefined); + + return { + subscribe, + setError: ( + e: WAError + ): void => set(e), + }; +} + +export const errorScreenStore = createErrorScreenStore(); diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index fae82184..973ce8ec 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -218,6 +218,18 @@ message ErrorMessage { string message = 1; } +message ErrorV2Message { + string type = 1; + string code = 2; + string title = 3; + string subtitle = 4; + string details = 5; + int32 timeToRetry = 6; + bool canRetryManual = 7; + string urlToRedirect = 8; + string buttonTitle = 9; +} + message ItemStateMessage { int32 itemId = 1; string stateJson = 2; @@ -329,6 +341,7 @@ message ServerToClientMessage { FollowAbortMessage followAbortMessage = 23; InvalidTextureMessage invalidTextureMessage = 24; GroupUsersUpdateMessage groupUsersUpdateMessage = 25; + ErrorV2Message errorV2Message = 26; } } diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index 5a5f857d..eb4af3a1 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -318,6 +318,8 @@ export class AuthenticateController extends BaseHttpController { (async () => { const param = await req.json(); + adminApi.setLocale(req.header('accept-language')); + //todo: what to do if the organizationMemberToken is already used? const organizationMemberToken: string | null = param.organizationMemberToken; const playUri: string | null = param.playUri; diff --git a/pusher/src/Controller/BaseHttpController.ts b/pusher/src/Controller/BaseHttpController.ts index a15f7529..17e08e0a 100644 --- a/pusher/src/Controller/BaseHttpController.ts +++ b/pusher/src/Controller/BaseHttpController.ts @@ -31,12 +31,14 @@ export class BaseHttpController { if (axios.isAxiosError(e) && e.response) { res.status(e.response.status); - res.send( - "An error occurred: " + - e.response.status + - " " + - (e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText) - ); + if(!e.response.data?.code) { + res.send( + "An error occurred: " + + e.response.status + + " " + + (e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText) + ); + } else res.json(e.response.data); return; } else { res.status(500); diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 6a2dccc1..90eadfe2 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -68,7 +68,7 @@ interface UpgradeData { interface UpgradeFailedData { rejected: true; - reason: "tokenInvalid" | "textureInvalid" | null; + reason: "tokenInvalid" | "textureInvalid" | "error" | null; message: string; roomId: string; } @@ -231,6 +231,8 @@ export class IoSocketController { const websocketExtensions = req.getHeader("sec-websocket-extensions"); const IPAddress = req.getHeader("x-forwarded-for"); + adminApi.setLocale(req.getHeader('accept-language')); + const roomId = query.roomId; try { if (typeof roomId !== "string") { @@ -306,7 +308,7 @@ export class IoSocketController { ); } catch (err) { if (Axios.isAxiosError(err)) { - if (err?.response?.status == 404) { + if (err?.response?.status == 404 || !err?.response?.data.code) { // If we get an HTTP 404, the token is invalid. Let's perform an anonymous login! console.warn( @@ -314,16 +316,18 @@ export class IoSocketController { (userIdentifier || "anonymous") + '". Performing an anonymous login instead.' ); - } else if (err?.response?.status == 403) { - // If we get an HTTP 403, the world is full. We need to broadcast a special error to the client. - // we finish immediately the upgrade then we will close the socket as soon as it starts opening. + } else if (err?.response?.data.code) { + //OLD // If we get an HTTP 403, the world is full. We need to broadcast a special error to the client. + //OLD // we finish immediately the upgrade then we will close the socket as soon as it starts opening. return res.upgrade( { rejected: true, - message: err?.response?.data.message, + reason: "error", + message: err?.response?.data.code, status: err?.response?.status, + error: err?.response?.data, roomId, - }, + } as UpgradeFailedData, websocketKey, websocketProtocol, websocketExtensions, @@ -476,8 +480,8 @@ export class IoSocketController { socketManager.emitTokenExpiredMessage(ws); } else if (ws.reason === "textureInvalid") { socketManager.emitInvalidTextureMessage(ws); - } else if (ws.message === "World is full") { - socketManager.emitWorldFullMessage(ws); + } else if (ws.reason === "error") { + socketManager.emitErrorV2Message(ws, ws.error.type, ws.error.code, ws.error.title, ws.error.subtitle, ws.error.details, ws.error.timeToRetry, ws.error.canRetryManual, ws.error.urlToRedirect, ws.error.buttonTitle); } else { socketManager.emitConnexionErrorMessage(ws, ws.message); } diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 1e5e98e8..13c060d6 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -31,6 +31,11 @@ const isFetchMemberDataByUuidResponse = new tg.IsInterface() export type FetchMemberDataByUuidResponse = tg.GuardedType; class AdminApi { + private locale: string = 'en'; + setLocale(locale: string){ + //console.info('PUSHER LOCALE SET TO :', locale); + this.locale = locale; + } /** * @var playUri: is url of the room * @var userId: can to be undefined or email or uuid @@ -47,7 +52,7 @@ class AdminApi { }; const res = await Axios.get>(ADMIN_API_URL + "/api/map", { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, params, }); if (!isMapDetailsData(res.data) && !isRoomRedirect(res.data)) { @@ -75,7 +80,7 @@ class AdminApi { ipAddress, characterLayers, }, - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, paramsSerializer: (p) => { return qs.stringify(p, { arrayFormat: "brackets" }); }, @@ -96,7 +101,7 @@ class AdminApi { //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, { params: { playUri }, - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, }); if (!isAdminApiData(res.data)) { console.error("Message received from /api/login-url is not in the expected format. Message: ", res.data); @@ -123,7 +128,7 @@ class AdminApi { reportWorldSlug, }, { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, } ); } @@ -142,7 +147,7 @@ class AdminApi { encodeURIComponent(userUuid) + "&roomUrl=" + encodeURIComponent(roomUrl), - { headers: { Authorization: `${ADMIN_API_TOKEN}` } } + { headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale } } ).then((data) => { return data.data; }); @@ -154,7 +159,7 @@ class AdminApi { } return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, }).then((data) => { return data.data; }); diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 37ad3689..5dc28835 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -39,7 +39,7 @@ import { WorldFullMessage, PlayerDetailsUpdatedMessage, LockGroupPromptMessage, - InvalidTextureMessage, + InvalidTextureMessage, ErrorV2Message, } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; @@ -644,6 +644,26 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } + public emitErrorV2Message(client: compressors.WebSocket, type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + const errorMessage = new ErrorV2Message(); + errorMessage.setType(type); + errorMessage.setCode(code); + errorMessage.setTitle(title); + errorMessage.setSubtitle(subtitle); + errorMessage.setDetails(details); + errorMessage.setTimetoretry(timeToRetry); + errorMessage.setCanretrymanual(canRetryManual); + errorMessage.setUrltoredirect(urlToRedirect); + errorMessage.setButtontitle(buttonTitle); + + const serverToClientMessage = new ServerToClientMessage(); + serverToClientMessage.setErrorv2message(errorMessage); + + //if (!client.disconnecting) { + client.send(serverToClientMessage.serializeBinary().buffer, true); + //} + } + private refreshRoomData(roomId: string, versionNumber: number): void { const room = this.rooms.get(roomId); //this function is run for every users connected to the room, so we need to make sure the room wasn't already refreshed. From 0b579418add61fe1a124a72804abbf61807b9217 Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 11:12:44 +0200 Subject: [PATCH 02/39] Fix prettier --- .../src/Controller/AuthenticateController.ts | 2 +- pusher/src/Controller/BaseHttpController.ts | 2 +- pusher/src/Controller/IoSocketController.ts | 15 +++++++++++++-- pusher/src/Services/AdminApi.ts | 16 ++++++++-------- pusher/src/Services/SocketManager.ts | 18 +++++++++++++++--- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index eb4af3a1..e1b8c84d 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -318,7 +318,7 @@ export class AuthenticateController extends BaseHttpController { (async () => { const param = await req.json(); - adminApi.setLocale(req.header('accept-language')); + adminApi.setLocale(req.header("accept-language")); //todo: what to do if the organizationMemberToken is already used? const organizationMemberToken: string | null = param.organizationMemberToken; diff --git a/pusher/src/Controller/BaseHttpController.ts b/pusher/src/Controller/BaseHttpController.ts index 17e08e0a..d12345c2 100644 --- a/pusher/src/Controller/BaseHttpController.ts +++ b/pusher/src/Controller/BaseHttpController.ts @@ -31,7 +31,7 @@ export class BaseHttpController { if (axios.isAxiosError(e) && e.response) { res.status(e.response.status); - if(!e.response.data?.code) { + if (!e.response.data?.code) { res.send( "An error occurred: " + e.response.status + diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 90eadfe2..bf44d92f 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -231,7 +231,7 @@ export class IoSocketController { const websocketExtensions = req.getHeader("sec-websocket-extensions"); const IPAddress = req.getHeader("x-forwarded-for"); - adminApi.setLocale(req.getHeader('accept-language')); + adminApi.setLocale(req.getHeader("accept-language")); const roomId = query.roomId; try { @@ -481,7 +481,18 @@ export class IoSocketController { } else if (ws.reason === "textureInvalid") { socketManager.emitInvalidTextureMessage(ws); } else if (ws.reason === "error") { - socketManager.emitErrorV2Message(ws, ws.error.type, ws.error.code, ws.error.title, ws.error.subtitle, ws.error.details, ws.error.timeToRetry, ws.error.canRetryManual, ws.error.urlToRedirect, ws.error.buttonTitle); + socketManager.emitErrorV2Message( + ws, + ws.error.type, + ws.error.code, + ws.error.title, + ws.error.subtitle, + ws.error.details, + ws.error.timeToRetry, + ws.error.canRetryManual, + ws.error.urlToRedirect, + ws.error.buttonTitle + ); } else { socketManager.emitConnexionErrorMessage(ws, ws.message); } diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 13c060d6..8ccc4e4b 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -31,8 +31,8 @@ const isFetchMemberDataByUuidResponse = new tg.IsInterface() export type FetchMemberDataByUuidResponse = tg.GuardedType; class AdminApi { - private locale: string = 'en'; - setLocale(locale: string){ + private locale: string = "en"; + setLocale(locale: string) { //console.info('PUSHER LOCALE SET TO :', locale); this.locale = locale; } @@ -52,7 +52,7 @@ class AdminApi { }; const res = await Axios.get>(ADMIN_API_URL + "/api/map", { - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, params, }); if (!isMapDetailsData(res.data) && !isRoomRedirect(res.data)) { @@ -80,7 +80,7 @@ class AdminApi { ipAddress, characterLayers, }, - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, paramsSerializer: (p) => { return qs.stringify(p, { arrayFormat: "brackets" }); }, @@ -101,7 +101,7 @@ class AdminApi { //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, { params: { playUri }, - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, }); if (!isAdminApiData(res.data)) { console.error("Message received from /api/login-url is not in the expected format. Message: ", res.data); @@ -128,7 +128,7 @@ class AdminApi { reportWorldSlug, }, { - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, } ); } @@ -147,7 +147,7 @@ class AdminApi { encodeURIComponent(userUuid) + "&roomUrl=" + encodeURIComponent(roomUrl), - { headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale } } + { headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale } } ).then((data) => { return data.data; }); @@ -159,7 +159,7 @@ class AdminApi { } return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), { - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, }).then((data) => { return data.data; }); diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 5dc28835..c644fc49 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -39,7 +39,8 @@ import { WorldFullMessage, PlayerDetailsUpdatedMessage, LockGroupPromptMessage, - InvalidTextureMessage, ErrorV2Message, + InvalidTextureMessage, + ErrorV2Message, } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; @@ -644,7 +645,18 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } - public emitErrorV2Message(client: compressors.WebSocket, type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + public emitErrorV2Message( + client: compressors.WebSocket, + type: string, + code: string, + title: string, + subtitle: string, + details: string, + timeToRetry: number, + canRetryManual: boolean, + urlToRedirect: string, + buttonTitle: string + ) { const errorMessage = new ErrorV2Message(); errorMessage.setType(type); errorMessage.setCode(code); @@ -660,7 +672,7 @@ export class SocketManager implements ZoneEventListener { serverToClientMessage.setErrorv2message(errorMessage); //if (!client.disconnecting) { - client.send(serverToClientMessage.serializeBinary().buffer, true); + client.send(serverToClientMessage.serializeBinary().buffer, true); //} } From 074f43d16c93a5995a686b253543f59fb8bbb80a Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 11:17:43 +0200 Subject: [PATCH 03/39] Fix Svelte depreciation reload --- front/src/Components/UI/ErrorScreen.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte index 276484b1..5e079a10 100644 --- a/front/src/Components/UI/ErrorScreen.svelte +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -14,7 +14,7 @@ function click(){ if(errorScreen.urlToRedirect) window.location.replace(errorScreen.urlToRedirect); else if(errorScreen.type === 'redirect' && window.history.length > 2) history.back(); - else window.location.reload(true); + else window.location.reload(); } let details = errorScreen.details; let timeVar = errorScreen.timeToRetry ?? 0; From d972b3a2e60624d84b0fa23a106ccf99cd9390a5 Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 11:22:58 +0200 Subject: [PATCH 04/39] Fix prettier for the front --- front/src/Components/App.svelte | 1 - front/src/Components/UI/ErrorScreen.svelte | 235 ++++++++++----------- front/src/Connexion/RoomConnection.ts | 6 +- front/src/Phaser/Login/EntryScene.ts | 26 +-- front/src/Phaser/Reconnecting/WAError.ts | 14 +- front/src/Stores/ErrorScreenStore.ts | 8 +- 6 files changed, 149 insertions(+), 141 deletions(-) diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index 3405aa71..da1ca6f0 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -16,7 +16,6 @@ import ErrorDialog from "./UI/ErrorDialog.svelte"; import ErrorScreen from "./UI/ErrorScreen.svelte"; - export let game: Game; diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte index 5e079a10..f01fc2e6 100644 --- a/front/src/Components/UI/ErrorScreen.svelte +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -7,152 +7,151 @@ import cup from "../images/cup.png"; import reload from "../images/reload.png"; import external from "../images/external-link.png"; - import {get} from "svelte/store"; + import { get } from "svelte/store"; let errorScreen = get(errorScreenStore); - function click(){ - if(errorScreen.urlToRedirect) window.location.replace(errorScreen.urlToRedirect); - else if(errorScreen.type === 'redirect' && window.history.length > 2) history.back(); + function click() { + if (errorScreen.urlToRedirect) window.location.replace(errorScreen.urlToRedirect); + else if (errorScreen.type === "redirect" && window.history.length > 2) history.back(); else window.location.reload(); } let details = errorScreen.details; let timeVar = errorScreen.timeToRetry ?? 0; - if(errorScreen.type === 'retry') { + if (errorScreen.type === "retry") { setInterval(() => { if (timeVar <= 1000) click(); timeVar -= 1000; }, 1000); } - $: detailsStylized = details.replace("{time}", `${timeVar/1000}`); - + $: detailsStylized = details.replace("{time}", `${timeVar / 1000}`);
- -
- {#if $errorScreenStore.type !== 'retry'}

{$errorScreenStore.title}

{/if} + +
+ {#if $errorScreenStore.type !== "retry"}

{$errorScreenStore.title}

{/if}

{$errorScreenStore.subtitle}

- {#if $errorScreenStore.type !== 'retry'}

Code : {$errorScreenStore.code}

{/if} -

{detailsStylized}{#if $errorScreenStore.type === 'retry'}

{/if}

- {#if ($errorScreenStore.type === 'retry' && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === 'redirect' && (window.history.length > 2 || $errorScreenStore.urlToRedirect))} + {#if $errorScreenStore.type !== "retry"}

Code : {$errorScreenStore.code}

{/if} +

+ {detailsStylized}{#if $errorScreenStore.type === "retry"}

{/if} +

+ {#if ($errorScreenStore.type === "retry" && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === "redirect" && (window.history.length > 2 || $errorScreenStore.urlToRedirect))}
- + {$errorScreenStore.buttonTitle}
{/if}
-
diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 6f12bbf3..04b07cf3 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -47,8 +47,8 @@ import { Subject } from "rxjs"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; import { gameManager } from "../Phaser/Game/GameManager"; import { SelectCharacterScene, SelectCharacterSceneName } from "../Phaser/Login/SelectCharacterScene"; -import {errorScreenStore} from "../Stores/ErrorScreenStore"; -import {WAError} from "../Phaser/Reconnecting/WAError"; +import { errorScreenStore } from "../Stores/ErrorScreenStore"; +import { WAError } from "../Phaser/Reconnecting/WAError"; const manualPingDelay = 20000; @@ -483,7 +483,7 @@ export class RoomConnection implements RoomConnection { } case "errorV2Message": { this._errorV2MessageStream.next(message.errorV2Message); - if(message.errorV2Message.code !== 'retry') this.closed = true; + if (message.errorV2Message.code !== "retry") this.closed = true; console.error("An error occurred server side: " + message.errorV2Message.code); errorScreenStore.setError(message.errorV2Message as unknown as WAError); break; diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 42c9f617..3c9ce919 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -5,7 +5,7 @@ import { WAError } from "../Reconnecting/WAError"; import { waScaleManager } from "../Services/WaScaleManager"; import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene"; import { localeDetector } from "../../i18n/locales"; -import {errorScreenStore} from "../../Stores/ErrorScreenStore"; +import { errorScreenStore } from "../../Stores/ErrorScreenStore"; export const EntrySceneName = "EntryScene"; @@ -47,17 +47,19 @@ export class EntryScene extends Scene { }) .catch((err) => { if (err.response.data?.code) { - errorScreenStore.setError(new WAError( - err.response.data.type, - err.response.data.code, - err.response.data.title, - err.response.data.subtitle, - err.response.data.details, - err.response.data.timeToRetry, - err.response.data.canRetryManual, - err.response.data.urlToRedirect, - err.response.data.buttonTitle - )); + errorScreenStore.setError( + new WAError( + err.response.data.type, + err.response.data.code, + err.response.data.title, + err.response.data.subtitle, + err.response.data.details, + err.response.data.timeToRetry, + err.response.data.canRetryManual, + err.response.data.urlToRedirect, + err.response.data.buttonTitle + ) + ); } else { ErrorScene.showError(err, this.scene); } diff --git a/front/src/Phaser/Reconnecting/WAError.ts b/front/src/Phaser/Reconnecting/WAError.ts index 84bc95ed..1481c54a 100644 --- a/front/src/Phaser/Reconnecting/WAError.ts +++ b/front/src/Phaser/Reconnecting/WAError.ts @@ -4,12 +4,22 @@ export class WAError extends Error { private _title: string; private _subtitle: string; private _details: string; - private _timeToRetry:number; + private _timeToRetry: number; private _canRetryManual: boolean; private _urlToRedirect: string; private _buttonTitle: string; - constructor(type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + constructor( + type: string, + code: string, + title: string, + subtitle: string, + details: string, + timeToRetry: number, + canRetryManual: boolean, + urlToRedirect: string, + buttonTitle: string + ) { super(title + " - " + subtitle + " - " + details); this._type = type; diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts index dc31b1cf..be00e03a 100644 --- a/front/src/Stores/ErrorScreenStore.ts +++ b/front/src/Stores/ErrorScreenStore.ts @@ -1,5 +1,5 @@ -import {writable} from "svelte/store"; -import {WAError} from "../Phaser/Reconnecting/WAError"; +import { writable } from "svelte/store"; +import { WAError } from "../Phaser/Reconnecting/WAError"; /** * A store that contains one error of type WAError to be displayed. @@ -9,9 +9,7 @@ function createErrorScreenStore() { return { subscribe, - setError: ( - e: WAError - ): void => set(e), + setError: (e: WAError): void => set(e), }; } From ecabdbe0c07287216891c9c774d519bd2fa2c4f6 Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 10:23:36 +0200 Subject: [PATCH 05/39] Refactoring Error Screen --- front/src/Components/App.svelte | 9 +- front/src/Components/UI/ErrorScreen.svelte | 158 ++++++++++++++++++ front/src/Components/images/button-large.png | Bin 0 -> 3571 bytes front/src/Components/images/cup.png | Bin 0 -> 1729 bytes front/src/Components/images/error.png | Bin 0 -> 4800 bytes front/src/Components/images/external-link.png | Bin 0 -> 10701 bytes .../src/Components/images/logo-min-white.png | Bin 0 -> 7558 bytes front/src/Components/images/reload.png | Bin 0 -> 3660 bytes front/src/Connexion/RoomConnection.ts | 13 ++ front/src/Phaser/Login/EntryScene.ts | 36 ++-- front/src/Phaser/Reconnecting/ErrorScene.ts | 7 - front/src/Phaser/Reconnecting/WAError.ts | 45 ++++- front/src/Stores/ErrorScreenStore.ts | 18 ++ messages/protos/messages.proto | 13 ++ .../src/Controller/AuthenticateController.ts | 2 + pusher/src/Controller/BaseHttpController.ts | 14 +- pusher/src/Controller/IoSocketController.ts | 22 ++- pusher/src/Services/AdminApi.ts | 17 +- pusher/src/Services/SocketManager.ts | 22 ++- 19 files changed, 315 insertions(+), 61 deletions(-) create mode 100644 front/src/Components/UI/ErrorScreen.svelte create mode 100644 front/src/Components/images/button-large.png create mode 100644 front/src/Components/images/cup.png create mode 100644 front/src/Components/images/error.png create mode 100644 front/src/Components/images/external-link.png create mode 100644 front/src/Components/images/logo-min-white.png create mode 100644 front/src/Components/images/reload.png create mode 100644 front/src/Stores/ErrorScreenStore.ts diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index c596c8ee..3405aa71 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -2,6 +2,7 @@ import type { Game } from "../Phaser/Game/Game"; import { chatVisibilityStore } from "../Stores/ChatStore"; import { errorStore } from "../Stores/ErrorStore"; + import { errorScreenStore } from "../Stores/ErrorScreenStore"; import { loginSceneVisibleStore } from "../Stores/LoginSceneStore"; import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; @@ -13,11 +14,17 @@ import SelectCharacterScene from "./selectCharacter/SelectCharacterScene.svelte"; import SelectCompanionScene from "./SelectCompanion/SelectCompanionScene.svelte"; import ErrorDialog from "./UI/ErrorDialog.svelte"; + import ErrorScreen from "./UI/ErrorScreen.svelte"; + export let game: Game; -{#if $errorStore.length > 0} +{#if $errorScreenStore !== undefined} +
+ +
+{:else if $errorStore.length > 0}
diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte new file mode 100644 index 00000000..276484b1 --- /dev/null +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -0,0 +1,158 @@ + + +
+
+ +
+ {#if $errorScreenStore.type !== 'retry'}

{$errorScreenStore.title}

{/if} +

{$errorScreenStore.subtitle}

+ {#if $errorScreenStore.type !== 'retry'}

Code : {$errorScreenStore.code}

{/if} +

{detailsStylized}{#if $errorScreenStore.type === 'retry'}

{/if}

+ {#if ($errorScreenStore.type === 'retry' && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === 'redirect' && (window.history.length > 2 || $errorScreenStore.urlToRedirect))} +
+ + {$errorScreenStore.buttonTitle} +
+ {/if} +
+ +
+ + diff --git a/front/src/Components/images/button-large.png b/front/src/Components/images/button-large.png new file mode 100644 index 0000000000000000000000000000000000000000..f1d52f50d0867a135f1003aec89f56343d2086ec GIT binary patch literal 3571 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 literal 0 HcmV?d00001 diff --git a/front/src/Components/images/cup.png b/front/src/Components/images/cup.png new file mode 100644 index 0000000000000000000000000000000000000000..2f0e15c324e66cb6fb29113f9e71c80da97ef816 GIT binary patch literal 1729 zcmai#X;cze6vt_D)GT!>bIh&H%9&gzYs?(c(v)$}@_6=_Sf8~6qQU~%BT*cA5{Fctt%y#aD|Iu}Qr<2XeQ zp8=fV@;RDuFeDnTQ-OrI9b?JR^28TQ@f(J zeOswQuc94K4*1GP>&=cZ-O%dy7vshshlH(|URmXQ0n6>`SYv1N*l&Qc0+rf!218; zy*!qV+^y1*v&X2nf=gJ26&IPL097!gBsFxC(FR#L-TaaSu*j|%p98QgiT zBy1|k1DWh%H1CaqE{tvMNQ1n#(7yg4fQ?NMIb(hFP>iR>guXl5q!A$RB$CqCKN_4 zGm4q>?h-K}Qo4GwrBKUcyTccj7rQSk_4Sr`!|JQO4`n=yq|GfXESxu_dqUs>>csCh z@qP#hm5vahD6z8m-uZCVdo3@UBTxcgHN5(sFT~fE`RTZjwpUK~smZP6n?QJzY_F2_ zI;5*iCcBrLn;SfMj3q+<)ZSEnGh&`vt(BC^6115YVB{hJs}jv^7)nBGK$=W*UF;hZ5JAf?5O%UzfNa#vG*A>4ZGq$SZE>^7;Fz&ihSj!Abc(+r zz5muaxeJBtyJJF4*#O~ajn0=ocBr|`fR2RlhJV8B`ja!!dd-f4=fv22kX!xdu96*mN@hV=|RvA zFl^RheV0lLh~r`$vp02N-v%Z;Y!Ptyk{ym;&uAx;$*Daym1~6yhn@=7!X6+4MHG)G zm)s@qFNT2SMv6BgM=C1a3`*4gLdA@|BYUV+7zl=Gv)6DLCX00bV$X@Wj~_b~PH|xb zKuEbec|b=91sy@M5dKOCp6(-y+FeRFWT!d90&gl3fXJ8V^T}w3FpFr2e(%79OGX~rtPaJee zxTvJMzl@n}T`XK}nMuE$S6*VB$EwB_xCJ!9S$e(Kkll~%S?e9O;nPFVr-E{?Alrx& zmHvW&hVgzBj7Sc=S5=3%_+`Q$MAD^rGVq>dmL54?C6#FH?~?QD>r(C7m1?RSD)Kk_ zo4n-6sx=d13gU_v^2tM*gGFWxZ}t#)K)i-K=)NV5k?mPvTE>oE z4H~U45HkKinvxTT`UbN-51)K%E@g4_pz_VpP}=;go@tokPXd5kyqv2}1>OA@0FrOa literal 0 HcmV?d00001 diff --git a/front/src/Components/images/error.png b/front/src/Components/images/error.png new file mode 100644 index 0000000000000000000000000000000000000000..a0fbc29b0a45a7c7a6f499a828a3ac052160449c GIT binary patch literal 4800 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%0DjG6@d(~DG;N#*SSWrBa@|J(9yE@;+A^FY? ze9V$boF2Iwy<)FaAR<35CkXZfXh}uUZV;MhBwcX=bL5E$SJ#fCVC;&l zcFf{06lGv|cjQb@G!sM2+1KXL%s}%Q{@8z-};zHi3t<{#S{qQ7joR#jyAKy2={sQoc~3=dYZ81QZUUbjuBAUo~Zo@-Ub z77xTK#Xx1zXrVM(CIeH!Xq7aY7iduwG)=x}abtBONFy zc)9|XQ4993WtMqy?fJ6hM-r+|ke& zO$?)Xfoes;hV(R^BQoe)pm2B8B7CpS!1TzGn!?=RKO51z_!{?Adn{|H$42z0ClHAWa3cYubr z2OIa`t?K;4g{PvjCB=b`YltrSxQfAG^Y^-0Gu?v=PMnTkhWeBZ{}uz%NQe&&7J=A)xDz#ts$wt!OkXemEh%F`q-?2zDP z*k^P8%xq1ICx3^GrC>@)ZQ3vb%8=*wA>rc62N&};#-=l;7z*I0g6*8I^Xi^kRpIK=v0}5O77q0>>)6(o14?T^H*k9Hd3KH~m L^>bP0l+XkKddGK2 literal 0 HcmV?d00001 diff --git a/front/src/Components/images/logo-min-white.png b/front/src/Components/images/logo-min-white.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5796b08ce5f3f9a8f630d21cce0e687eba10d0 GIT binary patch literal 7558 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 G_`d)$Xcq(); public readonly errorMessageStream = this._errorMessageStream.asObservable(); + private readonly _errorV2MessageStream = new Subject(); + public readonly errorV2MessageStream = this._errorV2MessageStream.asObservable(); + private readonly _roomJoinedMessageStream = new Subject<{ connection: RoomConnection; room: RoomJoinedMessageInterface; @@ -476,6 +482,13 @@ export class RoomConnection implements RoomConnection { console.error("An error occurred server side: " + message.errorMessage.message); break; } + case "errorV2Message": { + this._errorV2MessageStream.next(message.errorV2Message); + if(message.errorV2Message.code !== 'retry') this.closed = true; + console.error("An error occurred server side: " + message.errorV2Message.code); + errorScreenStore.setError(message.errorV2Message as unknown as WAError); + break; + } default: { // Security check: if we forget a "case", the line below will catch the error at compile-time. // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 41910f26..42c9f617 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -4,9 +4,8 @@ import { ErrorScene } from "../Reconnecting/ErrorScene"; import { WAError } from "../Reconnecting/WAError"; import { waScaleManager } from "../Services/WaScaleManager"; import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene"; -import LL from "../../i18n/i18n-svelte"; -import { get } from "svelte/store"; import { localeDetector } from "../../i18n/locales"; +import {errorScreenStore} from "../../Stores/ErrorScreenStore"; export const EntrySceneName = "EntryScene"; @@ -47,27 +46,18 @@ export class EntryScene extends Scene { this.scene.start(nextSceneName); }) .catch((err) => { - const $LL = get(LL); - if (err.response && err.response.status == 404) { - ErrorScene.showError( - new WAError( - $LL.error.accessLink.title(), - $LL.error.accessLink.subTitle(), - $LL.error.accessLink.details() - ), - this.scene - ); - } else if (err.response && err.response.status == 403) { - ErrorScene.showError( - new WAError( - $LL.error.connectionRejected.title(), - $LL.error.connectionRejected.subTitle({ - error: err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "", - }), - $LL.error.connectionRejected.details() - ), - this.scene - ); + if (err.response.data?.code) { + errorScreenStore.setError(new WAError( + err.response.data.type, + err.response.data.code, + err.response.data.title, + err.response.data.subtitle, + err.response.data.details, + err.response.data.timeToRetry, + err.response.data.canRetryManual, + err.response.data.urlToRedirect, + err.response.data.buttonTitle + )); } else { ErrorScene.showError(err, this.scene); } diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts index ea593c45..2e86983e 100644 --- a/front/src/Phaser/Reconnecting/ErrorScene.ts +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -3,7 +3,6 @@ import Image = Phaser.GameObjects.Image; import Sprite = Phaser.GameObjects.Sprite; import Text = Phaser.GameObjects.Text; import ScenePlugin = Phaser.Scenes.ScenePlugin; -import { WAError } from "./WAError"; import Axios from "axios"; export const ErrorSceneName = "ErrorScene"; @@ -88,12 +87,6 @@ export class ErrorScene extends Phaser.Scene { title: "An error occurred", subTitle: error, }); - } else if (error instanceof WAError) { - scene.start(ErrorSceneName, { - title: error.title, - subTitle: error.subTitle, - message: error.details, - }); } else if (Axios.isAxiosError(error) && error.response) { // Axios HTTP error // client received an error response (5xx, 4xx) diff --git a/front/src/Phaser/Reconnecting/WAError.ts b/front/src/Phaser/Reconnecting/WAError.ts index abc71f6c..84bc95ed 100644 --- a/front/src/Phaser/Reconnecting/WAError.ts +++ b/front/src/Phaser/Reconnecting/WAError.ts @@ -1,26 +1,55 @@ export class WAError extends Error { + private _type: string; + private _code: string; private _title: string; - private _subTitle: string; + private _subtitle: string; private _details: string; + private _timeToRetry:number; + private _canRetryManual: boolean; + private _urlToRedirect: string; + private _buttonTitle: string; - constructor(title: string, subTitle: string, details: string) { - super(title + " - " + subTitle + " - " + details); + constructor(type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + super(title + " - " + subtitle + " - " + details); + + this._type = type; + this._code = code; this._title = title; - this._subTitle = subTitle; + this._subtitle = subtitle; this._details = details; + this._timeToRetry = timeToRetry; + this._canRetryManual = canRetryManual; + this._urlToRedirect = urlToRedirect; + this._buttonTitle = buttonTitle; // Set the prototype explicitly. Object.setPrototypeOf(this, WAError.prototype); } + get type(): string { + return this._type; + } + get code(): string { + return this._code; + } get title(): string { return this._title; } - - get subTitle(): string { - return this._subTitle; + get subtitle(): string { + return this._subtitle; } - get details(): string { return this._details; } + get timeToRetry(): number { + return this._timeToRetry; + } + get buttonTitle(): string { + return this._buttonTitle; + } + get urlToRedirect(): string { + return this._urlToRedirect; + } + get canRetryManual(): boolean { + return this._canRetryManual; + } } diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts new file mode 100644 index 00000000..dc31b1cf --- /dev/null +++ b/front/src/Stores/ErrorScreenStore.ts @@ -0,0 +1,18 @@ +import {writable} from "svelte/store"; +import {WAError} from "../Phaser/Reconnecting/WAError"; + +/** + * A store that contains one error of type WAError to be displayed. + */ +function createErrorScreenStore() { + const { subscribe, set } = writable(undefined); + + return { + subscribe, + setError: ( + e: WAError + ): void => set(e), + }; +} + +export const errorScreenStore = createErrorScreenStore(); diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index fae82184..973ce8ec 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -218,6 +218,18 @@ message ErrorMessage { string message = 1; } +message ErrorV2Message { + string type = 1; + string code = 2; + string title = 3; + string subtitle = 4; + string details = 5; + int32 timeToRetry = 6; + bool canRetryManual = 7; + string urlToRedirect = 8; + string buttonTitle = 9; +} + message ItemStateMessage { int32 itemId = 1; string stateJson = 2; @@ -329,6 +341,7 @@ message ServerToClientMessage { FollowAbortMessage followAbortMessage = 23; InvalidTextureMessage invalidTextureMessage = 24; GroupUsersUpdateMessage groupUsersUpdateMessage = 25; + ErrorV2Message errorV2Message = 26; } } diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index 5a5f857d..eb4af3a1 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -318,6 +318,8 @@ export class AuthenticateController extends BaseHttpController { (async () => { const param = await req.json(); + adminApi.setLocale(req.header('accept-language')); + //todo: what to do if the organizationMemberToken is already used? const organizationMemberToken: string | null = param.organizationMemberToken; const playUri: string | null = param.playUri; diff --git a/pusher/src/Controller/BaseHttpController.ts b/pusher/src/Controller/BaseHttpController.ts index a15f7529..17e08e0a 100644 --- a/pusher/src/Controller/BaseHttpController.ts +++ b/pusher/src/Controller/BaseHttpController.ts @@ -31,12 +31,14 @@ export class BaseHttpController { if (axios.isAxiosError(e) && e.response) { res.status(e.response.status); - res.send( - "An error occurred: " + - e.response.status + - " " + - (e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText) - ); + if(!e.response.data?.code) { + res.send( + "An error occurred: " + + e.response.status + + " " + + (e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText) + ); + } else res.json(e.response.data); return; } else { res.status(500); diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 696abbfa..1d805102 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -69,7 +69,7 @@ interface UpgradeData { interface UpgradeFailedData { rejected: true; - reason: "tokenInvalid" | "textureInvalid" | null; + reason: "tokenInvalid" | "textureInvalid" | "error" | null; message: string; roomId: string; } @@ -236,6 +236,8 @@ export class IoSocketController { const websocketExtensions = req.getHeader("sec-websocket-extensions"); const IPAddress = req.getHeader("x-forwarded-for"); + adminApi.setLocale(req.getHeader('accept-language')); + const roomId = query.roomId; try { if (typeof roomId !== "string") { @@ -311,7 +313,7 @@ export class IoSocketController { ); } catch (err) { if (Axios.isAxiosError(err)) { - if (err?.response?.status == 404) { + if (err?.response?.status == 404 || !err?.response?.data.code) { // If we get an HTTP 404, the token is invalid. Let's perform an anonymous login! console.warn( @@ -319,16 +321,18 @@ export class IoSocketController { (userIdentifier || "anonymous") + '". Performing an anonymous login instead.' ); - } else if (err?.response?.status == 403) { - // If we get an HTTP 403, the world is full. We need to broadcast a special error to the client. - // we finish immediately the upgrade then we will close the socket as soon as it starts opening. + } else if (err?.response?.data.code) { + //OLD // If we get an HTTP 403, the world is full. We need to broadcast a special error to the client. + //OLD // we finish immediately the upgrade then we will close the socket as soon as it starts opening. return res.upgrade( { rejected: true, - message: err?.response?.data.message, + reason: "error", + message: err?.response?.data.code, status: err?.response?.status, + error: err?.response?.data, roomId, - }, + } as UpgradeFailedData, websocketKey, websocketProtocol, websocketExtensions, @@ -481,8 +485,8 @@ export class IoSocketController { socketManager.emitTokenExpiredMessage(ws); } else if (ws.reason === "textureInvalid") { socketManager.emitInvalidTextureMessage(ws); - } else if (ws.message === "World is full") { - socketManager.emitWorldFullMessage(ws); + } else if (ws.reason === "error") { + socketManager.emitErrorV2Message(ws, ws.error.type, ws.error.code, ws.error.title, ws.error.subtitle, ws.error.details, ws.error.timeToRetry, ws.error.canRetryManual, ws.error.urlToRedirect, ws.error.buttonTitle); } else { socketManager.emitConnexionErrorMessage(ws, ws.message); } diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 75ac002c..8a95fc86 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -26,6 +26,11 @@ export const isFetchMemberDataByUuidResponse = z.object({ export type FetchMemberDataByUuidResponse = z.infer; class AdminApi { + private locale: string = 'en'; + setLocale(locale: string){ + //console.info('PUSHER LOCALE SET TO :', locale); + this.locale = locale; + } /** * @var playUri: is url of the room * @var userId: can to be undefined or email or uuid @@ -42,7 +47,7 @@ class AdminApi { }; const res = await Axios.get>(ADMIN_API_URL + "/api/map", { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, params, }); @@ -80,7 +85,7 @@ class AdminApi { ipAddress, characterLayers, }, - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, paramsSerializer: (p) => { return qs.stringify(p, { arrayFormat: "brackets" }); }, @@ -106,7 +111,7 @@ class AdminApi { //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, { params: { playUri }, - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, }); const adminApiData = isAdminApiData.safeParse(res.data); @@ -138,7 +143,7 @@ class AdminApi { reportWorldSlug, }, { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, } ); } @@ -157,7 +162,7 @@ class AdminApi { encodeURIComponent(userUuid) + "&roomUrl=" + encodeURIComponent(roomUrl), - { headers: { Authorization: `${ADMIN_API_TOKEN}` } } + { headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale } } ).then((data) => { return data.data; }); @@ -169,7 +174,7 @@ class AdminApi { } return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, }).then((data) => { return data.data; }); diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 8f547cd2..3b1d8fe5 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -39,7 +39,7 @@ import { WorldFullMessage, PlayerDetailsUpdatedMessage, LockGroupPromptMessage, - InvalidTextureMessage, + InvalidTextureMessage, ErrorV2Message, } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; @@ -643,6 +643,26 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } + public emitErrorV2Message(client: compressors.WebSocket, type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + const errorMessage = new ErrorV2Message(); + errorMessage.setType(type); + errorMessage.setCode(code); + errorMessage.setTitle(title); + errorMessage.setSubtitle(subtitle); + errorMessage.setDetails(details); + errorMessage.setTimetoretry(timeToRetry); + errorMessage.setCanretrymanual(canRetryManual); + errorMessage.setUrltoredirect(urlToRedirect); + errorMessage.setButtontitle(buttonTitle); + + const serverToClientMessage = new ServerToClientMessage(); + serverToClientMessage.setErrorv2message(errorMessage); + + //if (!client.disconnecting) { + client.send(serverToClientMessage.serializeBinary().buffer, true); + //} + } + private refreshRoomData(roomId: string, versionNumber: number): void { const room = this.rooms.get(roomId); //this function is run for every users connected to the room, so we need to make sure the room wasn't already refreshed. From d4f856eb882948bf1e69344f996f51af48bb5b16 Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 11:12:44 +0200 Subject: [PATCH 06/39] Fix prettier --- .../src/Controller/AuthenticateController.ts | 2 +- pusher/src/Controller/BaseHttpController.ts | 2 +- pusher/src/Controller/IoSocketController.ts | 15 +++++++++++++-- pusher/src/Services/AdminApi.ts | 16 ++++++++-------- pusher/src/Services/SocketManager.ts | 18 +++++++++++++++--- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index eb4af3a1..e1b8c84d 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -318,7 +318,7 @@ export class AuthenticateController extends BaseHttpController { (async () => { const param = await req.json(); - adminApi.setLocale(req.header('accept-language')); + adminApi.setLocale(req.header("accept-language")); //todo: what to do if the organizationMemberToken is already used? const organizationMemberToken: string | null = param.organizationMemberToken; diff --git a/pusher/src/Controller/BaseHttpController.ts b/pusher/src/Controller/BaseHttpController.ts index 17e08e0a..d12345c2 100644 --- a/pusher/src/Controller/BaseHttpController.ts +++ b/pusher/src/Controller/BaseHttpController.ts @@ -31,7 +31,7 @@ export class BaseHttpController { if (axios.isAxiosError(e) && e.response) { res.status(e.response.status); - if(!e.response.data?.code) { + if (!e.response.data?.code) { res.send( "An error occurred: " + e.response.status + diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 1d805102..9bae7595 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -236,7 +236,7 @@ export class IoSocketController { const websocketExtensions = req.getHeader("sec-websocket-extensions"); const IPAddress = req.getHeader("x-forwarded-for"); - adminApi.setLocale(req.getHeader('accept-language')); + adminApi.setLocale(req.getHeader("accept-language")); const roomId = query.roomId; try { @@ -486,7 +486,18 @@ export class IoSocketController { } else if (ws.reason === "textureInvalid") { socketManager.emitInvalidTextureMessage(ws); } else if (ws.reason === "error") { - socketManager.emitErrorV2Message(ws, ws.error.type, ws.error.code, ws.error.title, ws.error.subtitle, ws.error.details, ws.error.timeToRetry, ws.error.canRetryManual, ws.error.urlToRedirect, ws.error.buttonTitle); + socketManager.emitErrorV2Message( + ws, + ws.error.type, + ws.error.code, + ws.error.title, + ws.error.subtitle, + ws.error.details, + ws.error.timeToRetry, + ws.error.canRetryManual, + ws.error.urlToRedirect, + ws.error.buttonTitle + ); } else { socketManager.emitConnexionErrorMessage(ws, ws.message); } diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 8a95fc86..ae12ed14 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -26,8 +26,8 @@ export const isFetchMemberDataByUuidResponse = z.object({ export type FetchMemberDataByUuidResponse = z.infer; class AdminApi { - private locale: string = 'en'; - setLocale(locale: string){ + private locale: string = "en"; + setLocale(locale: string) { //console.info('PUSHER LOCALE SET TO :', locale); this.locale = locale; } @@ -47,7 +47,7 @@ class AdminApi { }; const res = await Axios.get>(ADMIN_API_URL + "/api/map", { - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, params, }); @@ -85,7 +85,7 @@ class AdminApi { ipAddress, characterLayers, }, - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, paramsSerializer: (p) => { return qs.stringify(p, { arrayFormat: "brackets" }); }, @@ -111,7 +111,7 @@ class AdminApi { //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, { params: { playUri }, - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, }); const adminApiData = isAdminApiData.safeParse(res.data); @@ -143,7 +143,7 @@ class AdminApi { reportWorldSlug, }, { - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, } ); } @@ -162,7 +162,7 @@ class AdminApi { encodeURIComponent(userUuid) + "&roomUrl=" + encodeURIComponent(roomUrl), - { headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale } } + { headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale } } ).then((data) => { return data.data; }); @@ -174,7 +174,7 @@ class AdminApi { } return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), { - headers: { Authorization: `${ADMIN_API_TOKEN}`, 'Accept-Language': this.locale }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale }, }).then((data) => { return data.data; }); diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 3b1d8fe5..94369e3d 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -39,7 +39,8 @@ import { WorldFullMessage, PlayerDetailsUpdatedMessage, LockGroupPromptMessage, - InvalidTextureMessage, ErrorV2Message, + InvalidTextureMessage, + ErrorV2Message, } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; @@ -643,7 +644,18 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } - public emitErrorV2Message(client: compressors.WebSocket, type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + public emitErrorV2Message( + client: compressors.WebSocket, + type: string, + code: string, + title: string, + subtitle: string, + details: string, + timeToRetry: number, + canRetryManual: boolean, + urlToRedirect: string, + buttonTitle: string + ) { const errorMessage = new ErrorV2Message(); errorMessage.setType(type); errorMessage.setCode(code); @@ -659,7 +671,7 @@ export class SocketManager implements ZoneEventListener { serverToClientMessage.setErrorv2message(errorMessage); //if (!client.disconnecting) { - client.send(serverToClientMessage.serializeBinary().buffer, true); + client.send(serverToClientMessage.serializeBinary().buffer, true); //} } From c3289e8a0121b50711dbb0579ec649416d59be39 Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 11:17:43 +0200 Subject: [PATCH 07/39] Fix Svelte depreciation reload --- front/src/Components/UI/ErrorScreen.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte index 276484b1..5e079a10 100644 --- a/front/src/Components/UI/ErrorScreen.svelte +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -14,7 +14,7 @@ function click(){ if(errorScreen.urlToRedirect) window.location.replace(errorScreen.urlToRedirect); else if(errorScreen.type === 'redirect' && window.history.length > 2) history.back(); - else window.location.reload(true); + else window.location.reload(); } let details = errorScreen.details; let timeVar = errorScreen.timeToRetry ?? 0; From bf40bd2f3b1c0aaf5cd0c756651976a9c7acb4e4 Mon Sep 17 00:00:00 2001 From: CEC Date: Tue, 12 Apr 2022 11:22:58 +0200 Subject: [PATCH 08/39] Fix prettier for the front --- front/src/Components/App.svelte | 1 - front/src/Components/UI/ErrorScreen.svelte | 235 ++++++++++----------- front/src/Connexion/RoomConnection.ts | 6 +- front/src/Phaser/Login/EntryScene.ts | 26 +-- front/src/Phaser/Reconnecting/WAError.ts | 14 +- front/src/Stores/ErrorScreenStore.ts | 8 +- 6 files changed, 149 insertions(+), 141 deletions(-) diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index 3405aa71..da1ca6f0 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -16,7 +16,6 @@ import ErrorDialog from "./UI/ErrorDialog.svelte"; import ErrorScreen from "./UI/ErrorScreen.svelte"; - export let game: Game; diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte index 5e079a10..f01fc2e6 100644 --- a/front/src/Components/UI/ErrorScreen.svelte +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -7,152 +7,151 @@ import cup from "../images/cup.png"; import reload from "../images/reload.png"; import external from "../images/external-link.png"; - import {get} from "svelte/store"; + import { get } from "svelte/store"; let errorScreen = get(errorScreenStore); - function click(){ - if(errorScreen.urlToRedirect) window.location.replace(errorScreen.urlToRedirect); - else if(errorScreen.type === 'redirect' && window.history.length > 2) history.back(); + function click() { + if (errorScreen.urlToRedirect) window.location.replace(errorScreen.urlToRedirect); + else if (errorScreen.type === "redirect" && window.history.length > 2) history.back(); else window.location.reload(); } let details = errorScreen.details; let timeVar = errorScreen.timeToRetry ?? 0; - if(errorScreen.type === 'retry') { + if (errorScreen.type === "retry") { setInterval(() => { if (timeVar <= 1000) click(); timeVar -= 1000; }, 1000); } - $: detailsStylized = details.replace("{time}", `${timeVar/1000}`); - + $: detailsStylized = details.replace("{time}", `${timeVar / 1000}`);
- -
- {#if $errorScreenStore.type !== 'retry'}

{$errorScreenStore.title}

{/if} + +
+ {#if $errorScreenStore.type !== "retry"}

{$errorScreenStore.title}

{/if}

{$errorScreenStore.subtitle}

- {#if $errorScreenStore.type !== 'retry'}

Code : {$errorScreenStore.code}

{/if} -

{detailsStylized}{#if $errorScreenStore.type === 'retry'}

{/if}

- {#if ($errorScreenStore.type === 'retry' && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === 'redirect' && (window.history.length > 2 || $errorScreenStore.urlToRedirect))} + {#if $errorScreenStore.type !== "retry"}

Code : {$errorScreenStore.code}

{/if} +

+ {detailsStylized}{#if $errorScreenStore.type === "retry"}

{/if} +

+ {#if ($errorScreenStore.type === "retry" && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === "redirect" && (window.history.length > 2 || $errorScreenStore.urlToRedirect))}
- + {$errorScreenStore.buttonTitle}
{/if}
-
diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 7291fa17..5ec1e395 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -47,8 +47,8 @@ import { Subject } from "rxjs"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; import { gameManager } from "../Phaser/Game/GameManager"; import { SelectCharacterScene, SelectCharacterSceneName } from "../Phaser/Login/SelectCharacterScene"; -import {errorScreenStore} from "../Stores/ErrorScreenStore"; -import {WAError} from "../Phaser/Reconnecting/WAError"; +import { errorScreenStore } from "../Stores/ErrorScreenStore"; +import { WAError } from "../Phaser/Reconnecting/WAError"; const manualPingDelay = 20000; @@ -484,7 +484,7 @@ export class RoomConnection implements RoomConnection { } case "errorV2Message": { this._errorV2MessageStream.next(message.errorV2Message); - if(message.errorV2Message.code !== 'retry') this.closed = true; + if (message.errorV2Message.code !== "retry") this.closed = true; console.error("An error occurred server side: " + message.errorV2Message.code); errorScreenStore.setError(message.errorV2Message as unknown as WAError); break; diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 42c9f617..3c9ce919 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -5,7 +5,7 @@ import { WAError } from "../Reconnecting/WAError"; import { waScaleManager } from "../Services/WaScaleManager"; import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene"; import { localeDetector } from "../../i18n/locales"; -import {errorScreenStore} from "../../Stores/ErrorScreenStore"; +import { errorScreenStore } from "../../Stores/ErrorScreenStore"; export const EntrySceneName = "EntryScene"; @@ -47,17 +47,19 @@ export class EntryScene extends Scene { }) .catch((err) => { if (err.response.data?.code) { - errorScreenStore.setError(new WAError( - err.response.data.type, - err.response.data.code, - err.response.data.title, - err.response.data.subtitle, - err.response.data.details, - err.response.data.timeToRetry, - err.response.data.canRetryManual, - err.response.data.urlToRedirect, - err.response.data.buttonTitle - )); + errorScreenStore.setError( + new WAError( + err.response.data.type, + err.response.data.code, + err.response.data.title, + err.response.data.subtitle, + err.response.data.details, + err.response.data.timeToRetry, + err.response.data.canRetryManual, + err.response.data.urlToRedirect, + err.response.data.buttonTitle + ) + ); } else { ErrorScene.showError(err, this.scene); } diff --git a/front/src/Phaser/Reconnecting/WAError.ts b/front/src/Phaser/Reconnecting/WAError.ts index 84bc95ed..1481c54a 100644 --- a/front/src/Phaser/Reconnecting/WAError.ts +++ b/front/src/Phaser/Reconnecting/WAError.ts @@ -4,12 +4,22 @@ export class WAError extends Error { private _title: string; private _subtitle: string; private _details: string; - private _timeToRetry:number; + private _timeToRetry: number; private _canRetryManual: boolean; private _urlToRedirect: string; private _buttonTitle: string; - constructor(type: string, code: string, title: string, subtitle: string, details: string, timeToRetry: number, canRetryManual: boolean, urlToRedirect: string, buttonTitle: string) { + constructor( + type: string, + code: string, + title: string, + subtitle: string, + details: string, + timeToRetry: number, + canRetryManual: boolean, + urlToRedirect: string, + buttonTitle: string + ) { super(title + " - " + subtitle + " - " + details); this._type = type; diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts index dc31b1cf..be00e03a 100644 --- a/front/src/Stores/ErrorScreenStore.ts +++ b/front/src/Stores/ErrorScreenStore.ts @@ -1,5 +1,5 @@ -import {writable} from "svelte/store"; -import {WAError} from "../Phaser/Reconnecting/WAError"; +import { writable } from "svelte/store"; +import { WAError } from "../Phaser/Reconnecting/WAError"; /** * A store that contains one error of type WAError to be displayed. @@ -9,9 +9,7 @@ function createErrorScreenStore() { return { subscribe, - setError: ( - e: WAError - ): void => set(e), + setError: (e: WAError): void => set(e), }; } From 26dc8dbbafb24e1a9e98f7a48be4402b7081c2cd Mon Sep 17 00:00:00 2001 From: CEC Date: Wed, 13 Apr 2022 16:58:03 +0200 Subject: [PATCH 09/39] Review of changes asked to make code cleaner --- front/src/Components/UI/ErrorScreen.svelte | 24 +++++---------------- front/src/Connexion/RoomConnection.ts | 16 +++++++------- messages/protos/messages.proto | 10 +++++++-- pusher/src/Controller/IoSocketController.ts | 2 +- pusher/src/Services/SocketManager.ts | 8 +++---- 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte index f01fc2e6..ed8e5505 100644 --- a/front/src/Components/UI/ErrorScreen.svelte +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -1,8 +1,10 @@
@@ -44,9 +37,9 @@

{detailsStylized}{#if $errorScreenStore.type === "retry"}

{/if}

- {#if ($errorScreenStore.type === "retry" && $errorScreenStore.canRetryManual) || ($errorScreenStore.type === "unauthorized" && $errorScreenStore.urlToRedirect && $errorScreenStore.buttonTitle) || ($errorScreenStore.type === "redirect" && (window.history.length > 2 || $errorScreenStore.urlToRedirect))} + {#if $errorScreenStore.type === "retry" && $errorScreenStore.canRetryManual} {/if} diff --git a/front/src/Components/images/external-link.png b/front/src/Components/images/external-link.png deleted file mode 100644 index 52fca4ed38534972759e400790239bf642198fc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10701 zcmeAS@N?(olHy`uVBq!ia0y~yU=0W2NDeljNXA<0p9~BN44y8IAr*7p+;Pl}4is^{ z_+5*cqs75P@JeF{i?4u45Ran3p(kOou9Bg5FKtiB*5!C!7x_tU&t3+GhTR6n>C;&l zcFf{06lGv|cjQb@G!sM2+1KXL%s}%Q{@8z-};zHi3t<{#S{qQ7joR#jyAKy2={sQoc~3=dYZ81QZUUbjuBAUo~Zo@-Ub z77xTK#Xx1zXrVM(CIeH!Xq7aY7iduwG)=x}abtBONFy zc)9|XQ4993WtMqy?fJ6hM-r+|ke& zO$?)Xfoes;hV(R^BQoe)pm2B8B7CpS!1TzGn!?=RKO51z_!{?Adn{|H$42z0ClHAWa3cYubr z2OIa`t?K;4g{PvjCB=b`YltrSxQfAG^Y^-0Gu?v=PMnTkhWeBZ{}uz%NQe&&7J=A)xDz#ts$wt!OkXemEh%F`q-?2zDP z*k^P8%xq1ICx3^GrC>@)ZQ3vb%8=*wA>rc62N&};#-=l;7z*I0g6*8I^Xi^kRpIK=v0}5O77q0>>)6(o14?T^H*k9Hd3KH~m L^>bP0l+XkKddGK2 diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 02579af1..dce7216d 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -49,9 +49,9 @@ export class EntryScene extends Scene { .catch((err) => { const errorType = isErrorApiData.safeParse(err?.response?.data); if (errorType.success) { - if (errorType.data.type === 'unauthorized') { + if (errorType.data.type === "unauthorized") { void connectionManager.logout(); - } else if (errorType.data.type === 'redirect') { + } else if (errorType.data.type === "redirect") { window.location.assign(errorType.data.urlToRedirect); } else errorScreenStore.setError(err?.response?.data); } else { diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts index a9081b21..564afb92 100644 --- a/front/src/Stores/ErrorScreenStore.ts +++ b/front/src/Stores/ErrorScreenStore.ts @@ -10,7 +10,7 @@ function createErrorScreenStore() { return { subscribe, setError: (e: ErrorScreenMessage): void => { - set(e) + set(e); }, }; } diff --git a/messages/JsonMessages/ErrorApiData.ts b/messages/JsonMessages/ErrorApiData.ts index e9ea4e55..0fbf3db7 100644 --- a/messages/JsonMessages/ErrorApiData.ts +++ b/messages/JsonMessages/ErrorApiData.ts @@ -43,9 +43,4 @@ export const isErrorApiData = z.discriminatedUnion("type", [ isErrorApiUnauthorizedData, ]); -export type ErrorApiErrorData = z.infer; -export type ErrorApiRetryData = z.infer; -export type ErrorApiRedirectData = z.infer; -export type ErrorApiUnauthorizedData = z.infer; - export type ErrorApiData = z.infer; diff --git a/pusher/package.json b/pusher/package.json index 22f6960e..cbd5375e 100644 --- a/pusher/package.json +++ b/pusher/package.json @@ -40,6 +40,7 @@ }, "homepage": "https://github.com/thecodingmachine/workadventure#readme", "dependencies": { + "@anatine/zod-openapi": "^1.3.0", "axios": "^0.21.2", "circular-json": "^0.5.9", "debug": "^4.3.1", @@ -48,6 +49,7 @@ "hyper-express": "^5.8.1", "jsonwebtoken": "^8.5.1", "mkdirp": "^1.0.4", + "openapi3-ts": "^2.0.2", "openid-client": "^4.7.4", "prom-client": "^12.0.0", "qs": "^6.10.3", diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 3912d951..d985261a 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -247,7 +247,6 @@ export class IoSocketController { const IPAddress = req.getHeader("x-forwarded-for"); const locale = req.getHeader("accept-language"); - const roomId = query.roomId; try { if (typeof roomId !== "string") { @@ -345,7 +344,7 @@ export class IoSocketController { reason: null, status: 500, message: err?.response?.data, - roomId: roomId + roomId: roomId, } as UpgradeFailedData, websocketKey, websocketProtocol, diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 1476e89a..5bbfe32c 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -59,9 +59,10 @@ import { ErrorApiData, isErrorApiErrorData, isErrorApiRedirectData, - isErrorApiRetryData, isErrorApiUnauthorizedData + isErrorApiRetryData, + isErrorApiUnauthorizedData, } from "../Messages/JsonMessages/ErrorApiData"; -import {BoolValue, Int32Value, StringValue} from "google-protobuf/google/protobuf/wrappers_pb"; +import { BoolValue, Int32Value, StringValue } from "google-protobuf/google/protobuf/wrappers_pb"; const debug = Debug("socket"); @@ -681,20 +682,22 @@ export class SocketManager implements ZoneEventListener { public emitErrorScreenMessage(client: compressors.WebSocket, errorApi: ErrorApiData) { const errorMessage = new ErrorScreenMessage(); errorMessage.setType(errorApi.type); - if(errorApi.type == 'retry' || errorApi.type == 'error'){ + if (errorApi.type == "retry" || errorApi.type == "error") { errorMessage.setCode(new StringValue().setValue(errorApi.code)); errorMessage.setTitle(new StringValue().setValue(errorApi.title)); errorMessage.setSubtitle(new StringValue().setValue(errorApi.subtitle)); errorMessage.setDetails(new StringValue().setValue(errorApi.details)); errorMessage.setImage(new StringValue().setValue(errorApi.image)); } - if(errorApi.type == 'retry') { + if (errorApi.type == "retry") { if (errorApi.buttonTitle) errorMessage.setButtontitle(new StringValue().setValue(errorApi.buttonTitle)); - if (errorApi.canRetryManual !== undefined) errorMessage.setCanretrymanual(new BoolValue().setValue(errorApi.canRetryManual)); - if (errorApi.timeToRetry) errorMessage.setTimetoretry(new Int32Value().setValue(Number(errorApi.timeToRetry))); + if (errorApi.canRetryManual !== undefined) + errorMessage.setCanretrymanual(new BoolValue().setValue(errorApi.canRetryManual)); + if (errorApi.timeToRetry) + errorMessage.setTimetoretry(new Int32Value().setValue(Number(errorApi.timeToRetry))); } - if(errorApi.type == 'redirect' && errorApi.urlToRedirect) errorMessage.setUrltoredirect(new StringValue().setValue(errorApi.urlToRedirect)); - + if (errorApi.type == "redirect" && errorApi.urlToRedirect) + errorMessage.setUrltoredirect(new StringValue().setValue(errorApi.urlToRedirect)); const serverToClientMessage = new ServerToClientMessage(); serverToClientMessage.setErrorscreenmessage(errorMessage); From de6cbd7c0aa6393d57410c5be1111128aab67ddc Mon Sep 17 00:00:00 2001 From: CEC Date: Thu, 21 Apr 2022 14:49:41 +0200 Subject: [PATCH 39/39] Fix lint issues --- messages/JsonMessages/ErrorApiData.ts | 8 ++++---- pusher/src/Services/SocketManager.ts | 8 +------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/messages/JsonMessages/ErrorApiData.ts b/messages/JsonMessages/ErrorApiData.ts index 0fbf3db7..bb029159 100644 --- a/messages/JsonMessages/ErrorApiData.ts +++ b/messages/JsonMessages/ErrorApiData.ts @@ -7,7 +7,7 @@ import { z } from "zod"; export const isErrorApiErrorData = z.object({ // @ts-ignore - type: z.literal('error'), + type: z.literal("error"), code: z.string(), title: z.string(), subtitle: z.string(), @@ -16,7 +16,7 @@ export const isErrorApiErrorData = z.object({ }); export const isErrorApiRetryData = z.object({ - type: z.literal('retry'), + type: z.literal("retry"), code: z.string(), title: z.string(), subtitle: z.string(), @@ -28,12 +28,12 @@ export const isErrorApiRetryData = z.object({ }); export const isErrorApiRedirectData = z.object({ - type: z.literal('redirect'), + type: z.literal("redirect"), urlToRedirect: z.string(), }); export const isErrorApiUnauthorizedData = z.object({ - type: z.literal('unauthorized'), + type: z.literal("unauthorized"), }); export const isErrorApiData = z.discriminatedUnion("type", [ diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 5bbfe32c..9386824a 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -55,13 +55,7 @@ import { ExAdminSocketInterface } from "../Model/Websocket/ExAdminSocketInterfac import { compressors } from "hyper-express"; import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; import { adminService } from "./AdminService"; -import { - ErrorApiData, - isErrorApiErrorData, - isErrorApiRedirectData, - isErrorApiRetryData, - isErrorApiUnauthorizedData, -} from "../Messages/JsonMessages/ErrorApiData"; +import { ErrorApiData } from "../Messages/JsonMessages/ErrorApiData"; import { BoolValue, Int32Value, StringValue } from "google-protobuf/google/protobuf/wrappers_pb"; const debug = Debug("socket");