diff --git a/back/src/App.ts b/back/src/App.ts index a2aa91a5..545bdd91 100644 --- a/back/src/App.ts +++ b/back/src/App.ts @@ -7,7 +7,6 @@ import bodyParser = require('body-parser'); import * as http from "http"; import {MapController} from "./Controller/MapController"; import {PrometheusController} from "./Controller/PrometheusController"; -import {AdminController} from "./Controller/AdminController"; import {DebugController} from "./Controller/DebugController"; class App { @@ -17,7 +16,6 @@ class App { public authenticateController: AuthenticateController; public mapController: MapController; public prometheusController: PrometheusController; - private adminController: AdminController; private debugController: DebugController; constructor() { @@ -36,7 +34,6 @@ class App { this.authenticateController = new AuthenticateController(this.app); this.mapController = new MapController(this.app); this.prometheusController = new PrometheusController(this.app, this.ioSocketController); - this.adminController = new AdminController(this.app); this.debugController = new DebugController(this.app, this.ioSocketController); } diff --git a/back/src/Controller/AuthenticateController.ts b/back/src/Controller/AuthenticateController.ts index 26cc6ae5..d6ebe124 100644 --- a/back/src/Controller/AuthenticateController.ts +++ b/back/src/Controller/AuthenticateController.ts @@ -6,7 +6,14 @@ import { uuid } from 'uuidv4'; import Axios from "axios"; export interface TokenInterface { - name: string, + userUuid: string +} + +interface AdminApiData { + organizationSlug: string + worldSlug: string + roomSlug: string + mapUrlStart: string userUuid: string } @@ -35,20 +42,20 @@ export class AuthenticateController { return res.status(401).send('No admin backoffice set!'); } //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. - const response = await Axios.get(ADMIN_API_URL+'/api/login-url/'+organizationMemberToken, + const data = await Axios.get(ADMIN_API_URL+'/api/login-url/'+organizationMemberToken, { headers: {"Authorization" : `${ADMIN_API_TOKEN}`} } - ); + ).then((res): AdminApiData => res.data); - userUuid = response.data.userUuid; - mapUrlStart = response.data.mapUrlStart; - newUrl = this.getNewUrlOnAdminAuth(response.data) + userUuid = data.userUuid; + mapUrlStart = data.mapUrlStart; + newUrl = this.getNewUrlOnAdminAuth(data) } else { userUuid = uuid(); - mapUrlStart= URL_ROOM_STARTED; + mapUrlStart = req.headers.host?.replace('api.', 'maps.') + URL_ROOM_STARTED; newUrl = null; } - const authToken = Jwt.sign({userUuid: userUuid} as TokenInterface, SECRET_KEY, {expiresIn: '24h'}); + const authToken = Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '24h'}); return res.status(OK).send({ authToken, userUuid, @@ -64,7 +71,7 @@ export class AuthenticateController { }); } - getNewUrlOnAdminAuth(data:any): string { + private getNewUrlOnAdminAuth(data:AdminApiData): string { const organizationSlug = data.organizationSlug; const worldSlug = data.worldSlug; const roomSlug = data.roomSlug; diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 7111e7d2..3e18149f 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -121,18 +121,19 @@ export class IoSocketController { return next(new Error('Authentication error')); } Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => { + const tokenInterface = tokenDecoded as TokenInterface; if (err) { console.error('An authentication error happened, invalid JsonWebToken.', err); return next(new Error('Authentication error')); } - if (!this.isValidToken(tokenDecoded)) { + if (!this.isValidToken(tokenInterface)) { return next(new Error('Authentication error, invalid token structure')); } (socket as ExSocketInterface).token = socket.handshake.query.token; (socket as ExSocketInterface).userId = this.nextUserId; - (socket as ExSocketInterface).userUuid = tokenDecoded.userUuid; + (socket as ExSocketInterface).userUuid = tokenInterface.userUuid; this.nextUserId++; next(); }); @@ -141,11 +142,8 @@ export class IoSocketController { this.ioConnection(); } - private isValidToken(token: object): token is TokenInterface { - if (typeof((token as TokenInterface).userUuid) !== 'string') { - return false; - } - if (typeof((token as TokenInterface).name) !== 'string') { + private isValidToken(token: TokenInterface): boolean { + if (typeof(token.userUuid) !== 'string') { return false; } return true; diff --git a/back/src/Controller/MapController.ts b/back/src/Controller/MapController.ts index 58ce40a9..539eb9d7 100644 --- a/back/src/Controller/MapController.ts +++ b/back/src/Controller/MapController.ts @@ -3,6 +3,7 @@ import {Application, Request, Response} from "express"; import {OK} from "http-status-codes"; import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; +//todo: delete this export class MapController { App: Application; diff --git a/back/src/Model/Websocket/ExSocketInterface.ts b/back/src/Model/Websocket/ExSocketInterface.ts index ace374f4..3cacd7f5 100644 --- a/back/src/Model/Websocket/ExSocketInterface.ts +++ b/back/src/Model/Websocket/ExSocketInterface.ts @@ -1,7 +1,6 @@ import {Socket} from "socket.io"; import {PointInterface} from "./PointInterface"; import {Identificable} from "./Identificable"; -import {TokenInterface} from "../../Controller/AuthenticateController"; import {ViewportInterface} from "_Model/Websocket/ViewportMessage"; import {BatchMessage, SubMessage} from "../../Messages/generated/messages_pb"; diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index cb70eef3..6f8e67a5 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -2,51 +2,61 @@ import Axios from "axios"; import {API_URL} from "../Enum/EnvironmentVariable"; import {RoomConnection} from "./RoomConnection"; +interface LoginApiData { + authToken: string + userUuid: string + mapUrlStart: string + newUrl: string +} + class ConnectionManager { + private initPromise: Promise = Promise.reject(); private mapUrlStart: string|null = null; private authToken:string|null = null; private userUuid: string|null = null; - private userName:string|null = null; public async init(): Promise { const match = /\/register\/(.+)/.exec(window.location.toString()); const organizationMemberToken = match ? match[1] : null; - const res = await Axios.post(`${API_URL}/login`, {organizationMemberToken}); - this.authToken = res.data.authToken; - this.userUuid = res.data.userUuid; - this.mapUrlStart = res.data.mapUrlStart; - const newUrl = res.data.newUrl; + this.initPromise = Axios.post(`${API_URL}/login`, {organizationMemberToken}).then(res => res.data); + const data = await this.initPromise + this.authToken = data.authToken; + this.userUuid = data.userUuid; + this.mapUrlStart = data.mapUrlStart; + const newUrl = data.newUrl; if (newUrl) { history.pushState({}, '', newUrl); } } - public async setUserName(name:string): Promise { - //todo + public connectToRoomSocket(): Promise { + return new Promise((resolve, reject) => { + const connection = new RoomConnection(this.authToken as string); + connection.onConnectError((error: object) => { + console.log('An error occurred while connecting to socket server. Retrying'); + reject(error); + }); + resolve(connection); + }).catch((err) => { + // Let's retry in 4-6 seconds + return new Promise((resolve, reject) => { + setTimeout(() => { + //todo: allow a way to break recurrsion? + this.connectToRoomSocket().then((connection) => resolve(connection)); + }, 4000 + Math.floor(Math.random() * 2000) ); + }); + }); } - public connectToRoomSocket(): Promise { - return Axios.post(`${API_URL}/connectToSocket`, {authToken: this.authToken}).then((res) => { - return new Promise((resolve, reject) => { - const connection = new RoomConnection(res.data.roomToken); - connection.onConnectError((error: object) => { - console.log('An error occurred while connecting to socket server. Retrying'); - reject(error); - }); - resolve(connection); - }); - }) - .catch((err) => { - // Let's retry in 4-6 seconds - return new Promise((resolve, reject) => { - setTimeout(() => { - //todo: allow a way to break recurrsion? - this.connectToRoomSocket().then((connection) => resolve(connection)); - }, 4000 + Math.floor(Math.random() * 2000) ); - }); - }); + public getMapUrlStart(): Promise { + return this.initPromise.then(() => { + if (!this.mapUrlStart) { + throw new Error('No map url set!'); + } + return this.mapUrlStart; + }) } } diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 99ef7b4e..54519f60 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -83,9 +83,9 @@ export class RoomConnection implements RoomConnection { }) } - public emitPlayerDetailsMessage(characterLayersSelected: string[]) { + public emitPlayerDetailsMessage(userName: string, characterLayersSelected: string[]) { const message = new SetPlayerDetailsMessage(); - message.setName(name); + message.setName(userName); message.setCharacterlayersList(characterLayersSelected); this.socket.emit(EventMessage.SET_PLAYER_DETAILS, message.serializeBinary().buffer, (id: number) => { this.userId = id; diff --git a/front/src/Phaser/Game/AddPlayerInterface.ts b/front/src/Phaser/Game/AddPlayerInterface.ts index 519116ac..91563dd0 100644 --- a/front/src/Phaser/Game/AddPlayerInterface.ts +++ b/front/src/Phaser/Game/AddPlayerInterface.ts @@ -1,4 +1,4 @@ -import {PointInterface} from "../../Connexion/Connection"; +import {PointInterface} from "../../Connexion/ConnexionModels"; export interface AddPlayerInterface { userId: number; diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index 34a0bdf6..960ce7e2 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -4,7 +4,7 @@ import { } from "../../Connexion/ConnexionModels"; import Axios from "axios"; import {API_URL} from "../../Enum/EnvironmentVariable"; -import {adminDataFetchPromise} from "../../register"; +import {connectionManager} from "../../Connexion/ConnectionManager"; export interface HasMovedEvent { direction: string; @@ -30,23 +30,12 @@ export class GameManager { } loadStartMap() : Promise { - if (adminDataFetchPromise) { - return adminDataFetchPromise.then(data => { - return { - mapUrlStart: data.mapUrlStart, - startInstance: data.startInstance, - } - }) - } else { - //todo: remove this call, merge with the admin workflow? - return Axios.get(`${API_URL}/start-map`) - .then((res) => { - return res.data; - }).catch((err) => { - console.error(err); - throw err; - }); - } + return connectionManager.getMapUrlStart().then(mapUrlStart => { + return { + mapUrlStart: mapUrlStart, + startInstance: "global", //todo: is this property still usefull? + } + }); } getPlayerName(): string { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 163eb3dc..425aaf36 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -205,8 +205,8 @@ export class GameScene extends Phaser.Scene implements CenterListener { this.connectionPromise = connectionManager.connectToRoomSocket().then((connection : RoomConnection) => { this.connection = connection; - - this.connection.emitPlayerDetailsMessage(gameManager.getCharacterSelected()) + + this.connection.emitPlayerDetailsMessage(gameManager.getPlayerName(), gameManager.getCharacterSelected()) connection.onUserJoins((message: MessageUserJoined) => { const userMessage: AddPlayerInterface = {