diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 20a7b7d5..02579af1 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -49,11 +49,11 @@ export class EntryScene extends Scene { .catch((err) => { const errorType = isErrorApiData.safeParse(err?.response?.data); if (errorType.success) { - // If error from API and urlToRedirect is specified but not buttonTitle => redirect directly - if (!errorType.data.buttonTitle && errorType.data.urlToRedirect) { - if (errorType.data.urlToRedirect === "/login") void connectionManager.logout(); - else window.location.assign(errorType.data.urlToRedirect); - } else errorScreenStore.setError(err.response.data); + if (errorType.data.type === 'unauthorized') { + void connectionManager.logout(); + } else if (errorType.data.type === 'redirect') { + window.location.assign(errorType.data.urlToRedirect); + } else errorScreenStore.setError(err?.response?.data); } else { ErrorScene.showError(err, this.scene); } diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts index eeb456c1..a9081b21 100644 --- a/front/src/Stores/ErrorScreenStore.ts +++ b/front/src/Stores/ErrorScreenStore.ts @@ -9,7 +9,9 @@ function createErrorScreenStore() { return { subscribe, - setError: (e: ErrorScreenMessage): void => set(e), + setError: (e: ErrorScreenMessage): void => { + set(e) + }, }; } diff --git a/messages/JsonMessages/ErrorApiData.ts b/messages/JsonMessages/ErrorApiData.ts index a50d72f5..e9ea4e55 100644 --- a/messages/JsonMessages/ErrorApiData.ts +++ b/messages/JsonMessages/ErrorApiData.ts @@ -5,17 +5,47 @@ import { z } from "zod"; * All other files are automatically copied from this file on container startup / build */ -export const isErrorApiData = z.object({ - type: z.string(), +export const isErrorApiErrorData = z.object({ + // @ts-ignore + type: z.literal('error'), code: z.string(), title: z.string(), subtitle: z.string(), details: z.string(), image: z.string(), - urlToRedirect: z.optional(z.nullable(z.string())), - buttonTitle: z.optional(z.nullable(z.string())), - timeToRetry: z.optional(z.nullable(z.bigint())), - canRetryManual: z.optional(z.nullable(z.boolean())), }); +export const isErrorApiRetryData = z.object({ + type: z.literal('retry'), + code: z.string(), + title: z.string(), + subtitle: z.string(), + details: z.string(), + image: z.string(), + buttonTitle: z.optional(z.nullable(z.string())), + timeToRetry: z.number(), + canRetryManual: z.boolean(), +}); + +export const isErrorApiRedirectData = z.object({ + type: z.literal('redirect'), + urlToRedirect: z.string(), +}); + +export const isErrorApiUnauthorizedData = z.object({ + type: z.literal('unauthorized'), +}); + +export const isErrorApiData = z.discriminatedUnion("type", [ + isErrorApiErrorData, + isErrorApiRetryData, + isErrorApiRedirectData, + 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/messages/protos/messages.proto b/messages/protos/messages.proto index 1291d6f3..40ddb373 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -226,15 +226,15 @@ message ErrorMessage { */ message ErrorScreenMessage { 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; - string image = 10; + google.protobuf.StringValue code = 2; + google.protobuf.StringValue title = 3; + google.protobuf.StringValue subtitle = 4; + google.protobuf.StringValue details = 5; + google.protobuf.Int32Value timeToRetry = 6; + google.protobuf.BoolValue canRetryManual = 7; + google.protobuf.StringValue urlToRedirect = 8; + google.protobuf.StringValue buttonTitle = 9; + google.protobuf.StringValue image = 10; } message ItemStateMessage { diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index baa463a2..3912d951 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -245,6 +245,8 @@ export class IoSocketController { const websocketProtocol = req.getHeader("sec-websocket-protocol"); const websocketExtensions = req.getHeader("sec-websocket-extensions"); const IPAddress = req.getHeader("x-forwarded-for"); + const locale = req.getHeader("accept-language"); + const roomId = query.roomId; try { @@ -318,7 +320,7 @@ export class IoSocketController { roomId, IPAddress, characterLayers, - req.getHeader("accept-language") + locale ); } catch (err) { if (Axios.isAxiosError(err)) { @@ -336,6 +338,20 @@ export class IoSocketController { websocketExtensions, context ); + } else { + return res.upgrade( + { + rejected: true, + reason: null, + status: 500, + message: err?.response?.data, + roomId: roomId + } as UpgradeFailedData, + websocketKey, + websocketProtocol, + websocketExtensions, + context + ); } } throw err; diff --git a/pusher/src/Controller/MapController.ts b/pusher/src/Controller/MapController.ts index b08e2091..0dd98b6a 100644 --- a/pusher/src/Controller/MapController.ts +++ b/pusher/src/Controller/MapController.ts @@ -108,9 +108,9 @@ export class MapController extends BaseHttpController { try { const mapDetails = isMapDetailsData.parse( await adminService.fetchMapDetails( - req.header("accept-language"), query.playUri as string, - query.authToken as string + query.authToken as string, + req.header("accept-language") ) ); diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 54697062..1476e89a 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -55,7 +55,13 @@ import { ExAdminSocketInterface } from "../Model/Websocket/ExAdminSocketInterfac import { compressors } from "hyper-express"; import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; import { adminService } from "./AdminService"; -import { ErrorApiData } from "../Messages/JsonMessages/ErrorApiData"; +import { + ErrorApiData, + isErrorApiErrorData, + isErrorApiRedirectData, + isErrorApiRetryData, isErrorApiUnauthorizedData +} from "../Messages/JsonMessages/ErrorApiData"; +import {BoolValue, Int32Value, StringValue} from "google-protobuf/google/protobuf/wrappers_pb"; const debug = Debug("socket"); @@ -472,7 +478,7 @@ export class SocketManager implements ZoneEventListener { } public async updateRoomWithAdminData(room: PusherRoom): Promise { - const data = await adminService.fetchMapDetails("en", room.roomUrl); + const data = await adminService.fetchMapDetails(room.roomUrl); const mapDetailsData = isMapDetailsData.safeParse(data); if (mapDetailsData.success) { @@ -672,21 +678,23 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } - public emitErrorScreenMessage(client: compressors.WebSocket, error: ErrorApiData) { + public emitErrorScreenMessage(client: compressors.WebSocket, errorApi: ErrorApiData) { const errorMessage = new ErrorScreenMessage(); - errorMessage.setType(error.type); - errorMessage.setCode(error.code); - errorMessage.setTitle(error.title); - errorMessage.setSubtitle(error.subtitle); - errorMessage.setDetails(error.details); - errorMessage.setImage(error.image); + errorMessage.setType(errorApi.type); + 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.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.type == 'redirect' && errorApi.urlToRedirect) errorMessage.setUrltoredirect(new StringValue().setValue(errorApi.urlToRedirect)); - if (error.urlToRedirect) errorMessage.setUrltoredirect(error.urlToRedirect); - if (error.buttonTitle) errorMessage.setButtontitle(error.buttonTitle); - if (error.canRetryManual !== undefined && null !== error.canRetryManual) - errorMessage.setCanretrymanual(error.canRetryManual); - if (error.timeToRetry && !isNaN(Number(error.timeToRetry))) - errorMessage.setTimetoretry(Number(error.timeToRetry)); const serverToClientMessage = new ServerToClientMessage(); serverToClientMessage.setErrorscreenmessage(errorMessage);