From b1f8522c0511365d3c7ceac3ff2e0ac1d52d732c Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Fri, 15 Jan 2021 03:19:58 +0100 Subject: [PATCH 01/17] Create ban feature by admin console --- back/src/Model/Admin.ts | 14 ++++++-------- back/src/Model/GameRoom.ts | 18 ++++++++++++++---- back/src/Model/User.ts | 1 + back/tests/GameRoomTest.ts | 1 + messages/protos/messages.proto | 5 +++-- pusher/src/Controller/IoSocketController.ts | 6 +++++- .../src/Model/Websocket/ExSocketInterface.ts | 1 + pusher/src/Services/AdminApi.ts | 17 +++++++++++++++++ pusher/src/Services/JWTTokenManager.ts | 15 +++++++++++++-- pusher/src/Services/SocketManager.ts | 16 +++++++--------- 10 files changed, 68 insertions(+), 26 deletions(-) diff --git a/back/src/Model/Admin.ts b/back/src/Model/Admin.ts index aa4bd328..53757e96 100644 --- a/back/src/Model/Admin.ts +++ b/back/src/Model/Admin.ts @@ -21,17 +21,15 @@ export class Admin { ) { } - public sendUserJoin(uuid: string): void { - const serverToAdminClientMessage = new ServerToAdminClientMessage(); - serverToAdminClientMessage.setUseruuidjoinedroom(uuid); - + public sendUserJoin(uuid: string, name: string, ip: string): void { + let serverToAdminClientMessage = new ServerToAdminClientMessage(); + serverToAdminClientMessage = serverToAdminClientMessage.setUseruuidnamejoinedroom(uuid+';'+name+';'+ip) this.socket.write(serverToAdminClientMessage); } - public sendUserLeft(uuid: string): void { - const serverToAdminClientMessage = new ServerToAdminClientMessage(); - serverToAdminClientMessage.setUseruuidleftroom(uuid); - + public sendUserLeft(uuid: string, name: string, ip: string): void { + let serverToAdminClientMessage = new ServerToAdminClientMessage(); + serverToAdminClientMessage = serverToAdminClientMessage.setUseruuidnameleftroom(uuid+';'+name+';'+ip); this.socket.write(serverToAdminClientMessage); } } diff --git a/back/src/Model/GameRoom.ts b/back/src/Model/GameRoom.ts index 129b0ac8..8a57ee99 100644 --- a/back/src/Model/GameRoom.ts +++ b/back/src/Model/GameRoom.ts @@ -102,7 +102,17 @@ export class GameRoom { } const position = ProtobufUtils.toPointInterface(positionMessage); - const user = new User(this.nextUserId, joinRoomMessage.getUseruuid(), position, false, this.positionNotifier, socket, joinRoomMessage.getTagList(), joinRoomMessage.getName(), ProtobufUtils.toCharacterLayerObjects(joinRoomMessage.getCharacterlayerList())); + const user = new User(this.nextUserId, + joinRoomMessage.getUseruuid(), + joinRoomMessage.getIpaddress(), + position, + false, + this.positionNotifier, + socket, + joinRoomMessage.getTagList(), + joinRoomMessage.getName(), + ProtobufUtils.toCharacterLayerObjects(joinRoomMessage.getCharacterlayerList()) + ); this.nextUserId++; this.users.set(user.id, user); this.usersByUuid.set(user.uuid, user); @@ -112,7 +122,7 @@ export class GameRoom { // Notify admins for (const admin of this.admins) { - admin.sendUserJoin(user.uuid); + admin.sendUserJoin(user.uuid, user.name, user.IPAddress); } return user; @@ -135,7 +145,7 @@ export class GameRoom { // Notify admins for (const admin of this.admins) { - admin.sendUserLeft(user.uuid); + admin.sendUserLeft(user.uuid, user.name, user.IPAddress); } } @@ -318,7 +328,7 @@ export class GameRoom { // Let's send all connected users for (const user of this.users.values()) { - admin.sendUserJoin(user.uuid); + admin.sendUserJoin(user.uuid, user.name, user.IPAddress); } } diff --git a/back/src/Model/User.ts b/back/src/Model/User.ts index 2bc3ee22..51a1a617 100644 --- a/back/src/Model/User.ts +++ b/back/src/Model/User.ts @@ -16,6 +16,7 @@ export class User implements Movable { public constructor( public id: number, public readonly uuid: string, + public readonly IPAddress: string, private position: PointInterface, public silent: boolean, private positionNotifier: PositionNotifier, diff --git a/back/tests/GameRoomTest.ts b/back/tests/GameRoomTest.ts index 3dc9aada..45721334 100644 --- a/back/tests/GameRoomTest.ts +++ b/back/tests/GameRoomTest.ts @@ -26,6 +26,7 @@ function createJoinRoomMessage(uuid: string, x: number, y: number): JoinRoomMess positionMessage.setMoving(false); const joinRoomMessage = new JoinRoomMessage(); joinRoomMessage.setUseruuid('1'); + joinRoomMessage.setIpaddress('10.0.0.2'); joinRoomMessage.setName('foo'); joinRoomMessage.setRoomid('_/global/test.json'); joinRoomMessage.setPositionmessage(positionMessage); diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 24db45d5..0e92f381 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -220,6 +220,7 @@ message JoinRoomMessage { string userUuid = 4; string roomId = 5; repeated string tag = 6; + string IPAddress = 7; } message UserJoinedZoneMessage { @@ -308,8 +309,8 @@ message ServerToAdminClientMessage { message ServerToAdminClientMessage { oneof message { - string userUuidJoinedRoom = 1; - string userUuidLeftRoom = 2; + string userUuidNameJoinedRoom = 1; + string userUuidNameLeftRoom = 2; } } diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 58cf05fb..a8bedabb 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -148,6 +148,7 @@ export class IoSocketController { const websocketKey = req.getHeader('sec-websocket-key'); const websocketProtocol = req.getHeader('sec-websocket-protocol'); const websocketExtensions = req.getHeader('sec-websocket-extensions'); + const IPAddress = req.getHeader('x-forwarded-for'); const roomId = query.roomId; if (typeof roomId !== 'string') { @@ -177,7 +178,8 @@ export class IoSocketController { } const userUuid = await jwtTokenManager.getUserUuidFromToken(token); - + //TODO send ban message + await jwtTokenManager.verifyBanUser(userUuid, IPAddress, roomId); let memberTags: string[] = []; let memberTextures: CharacterTexture[] = []; const room = await socketManager.getOrCreateRoom(roomId); @@ -217,6 +219,7 @@ export class IoSocketController { url, token, userUuid, + IPAddress, roomId, name, characterLayers: characterLayerObjs, @@ -336,6 +339,7 @@ export class IoSocketController { client.userId = this.nextUserId; this.nextUserId++; client.userUuid = ws.userUuid; + client.IPAddress = ws.IPAddress; client.token = ws.token; client.batchedMessages = new BatchMessage(); client.batchTimeout = null; diff --git a/pusher/src/Model/Websocket/ExSocketInterface.ts b/pusher/src/Model/Websocket/ExSocketInterface.ts index b8ee4bc8..85cfad48 100644 --- a/pusher/src/Model/Websocket/ExSocketInterface.ts +++ b/pusher/src/Model/Websocket/ExSocketInterface.ts @@ -24,6 +24,7 @@ export interface ExSocketInterface extends WebSocket, Identificable { roomId: string; //userId: number; // A temporary (autoincremented) identifier for this user userUuid: string; // A unique identifier for this user + IPAddress: string; // IP address name: string; characterLayers: CharacterLayer[]; position: PointInterface; diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 9c46a41b..75977482 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -14,6 +14,11 @@ export interface AdminApiData { textures: CharacterTexture[] } +export interface AdminBannedData { + is_banned: boolean, + message: string +} + export interface CharacterTexture { id: number, level: number, @@ -110,6 +115,18 @@ class AdminApi { headers: {"Authorization": `${ADMIN_API_TOKEN}`} }); } + + async verifyBanUser(organizationMemberToken: string, ipAddress: string, room: string): Promise { + if (!ADMIN_API_URL) { + return Promise.reject('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. + return Axios.get(ADMIN_API_URL + '/api/check-moderate-user/' + ipAddress + '/' + organizationMemberToken + '/room/' + room, + {headers: {"Authorization": `${ADMIN_API_TOKEN}`}} + ).then((data) => { + return data.data; + }); + } } export const adminApi = new AdminApi(); diff --git a/pusher/src/Services/JWTTokenManager.ts b/pusher/src/Services/JWTTokenManager.ts index 8abb0e45..ca692b77 100644 --- a/pusher/src/Services/JWTTokenManager.ts +++ b/pusher/src/Services/JWTTokenManager.ts @@ -2,7 +2,7 @@ import {ADMIN_API_URL, ALLOW_ARTILLERY, SECRET_KEY} from "../Enum/EnvironmentVar import {uuid} from "uuidv4"; import Jwt from "jsonwebtoken"; import {TokenInterface} from "../Controller/AuthenticateController"; -import {adminApi, AdminApiData} from "../Services/AdminApi"; +import {adminApi, AdminBannedData} from "../Services/AdminApi"; class JWTTokenManager { @@ -54,7 +54,7 @@ class JWTTokenManager { resolve(tokenInterface.userUuid); }).catch((err) => { //anonymous user - if(err.response && err.response.status && err.response.status === 404){ + if (err.response && err.response.status && err.response.status === 404) { resolve(tokenInterface.userUuid); return; } @@ -67,6 +67,17 @@ class JWTTokenManager { }); } + public async verifyBanUser(userUuid: string, ipAddress: string, room: string): Promise { + room = room.split('/').join('_'); + return adminApi.verifyBanUser(userUuid, ipAddress, room).then((data: AdminBannedData) => { + if (data && data.is_banned) { + throw new Error('User was banned'); + } + }).catch((err) => { + throw err; + }); + } + private isValidToken(token: object): token is TokenInterface { return !(typeof((token as TokenInterface).userUuid) !== 'string'); } diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 6255ca20..df944b9e 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -79,23 +79,20 @@ export class SocketManager implements ZoneEventListener { } async handleAdminRoom(client: ExAdminSocketInterface, roomId: string): Promise { - console.log('Calling adminRoom') const apiClient = await apiClientRepository.getClient(roomId); const adminRoomStream = apiClient.adminRoom(); client.adminConnection = adminRoomStream; adminRoomStream.on('data', (message: ServerToAdminClientMessage) => { - if (message.hasUseruuidjoinedroom()) { - const userUuid = message.getUseruuidjoinedroom(); - + if (message.hasUseruuidnamejoinedroom()) { + const userUuidName = message.getUseruuidnamejoinedroom(); if (!client.disconnecting) { - client.send('MemberJoin:'+userUuid+';'+roomId); + client.send('MemberJoin:'+userUuidName+';'+roomId); } - } else if (message.hasUseruuidleftroom()) { - const userUuid = message.getUseruuidleftroom(); - + } else if (message.hasUseruuidnameleftroom()) { + const userUuidName = message.getUseruuidnameleftroom(); if (!client.disconnecting) { - client.send('MemberLeave:'+userUuid+';'+roomId); + client.send('MemberLeave:'+userUuidName+';'+roomId); } } else { throw new Error('Unexpected admin message'); @@ -151,6 +148,7 @@ export class SocketManager implements ZoneEventListener { const joinRoomMessage = new JoinRoomMessage(); joinRoomMessage.setUseruuid(client.userUuid); + joinRoomMessage.setIpaddress(client.IPAddress); joinRoomMessage.setRoomid(client.roomId); joinRoomMessage.setName(client.name); joinRoomMessage.setPositionmessage(ProtobufUtils.toPositionMessage(client.position)); From a7398fa851344dd5f9c7c39e03758b01752fbb73 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Fri, 15 Jan 2021 05:12:23 +0100 Subject: [PATCH 02/17] Fix ci --- back/tests/PositionNotifierTest.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/back/tests/PositionNotifierTest.ts b/back/tests/PositionNotifierTest.ts index 94b49ab7..5901202f 100644 --- a/back/tests/PositionNotifierTest.ts +++ b/back/tests/PositionNotifierTest.ts @@ -25,14 +25,14 @@ describe("PositionNotifier", () => { leaveTriggered = true; }); - const user1 = new User(1, 'test', { + const user1 = new User(1, 'test', '10.0.0.2', { x: 500, y: 500, moving: false, direction: 'down' }, false, positionNotifier, {} as UserSocket, [], 'foo', []); - const user2 = new User(2, 'test', { + const user2 = new User(2, 'test', '10.0.0.2', { x: -9999, y: -9999, moving: false, @@ -100,14 +100,14 @@ describe("PositionNotifier", () => { leaveTriggered = true; }); - const user1 = new User(1, 'test', { + const user1 = new User(1, 'test', '10.0.0.2', { x: 500, y: 500, moving: false, direction: 'down' }, false, positionNotifier, {} as UserSocket, [], 'foo', []); - const user2 = new User(2, 'test', { + const user2 = new User(2, 'test', '10.0.0.2', { x: 0, y: 0, moving: false, From 74d05942467bcbd56cbf141e3163f0cd3fe45933 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 16 Jan 2021 20:14:21 +0100 Subject: [PATCH 03/17] Fix feedback @moufmou --- pusher/src/Controller/IoSocketController.ts | 5 ++-- pusher/src/Services/JWTTokenManager.ts | 27 ++++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index a8bedabb..63019b7d 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -177,9 +177,8 @@ export class IoSocketController { characterLayers = [ characterLayers ]; } - const userUuid = await jwtTokenManager.getUserUuidFromToken(token); - //TODO send ban message - await jwtTokenManager.verifyBanUser(userUuid, IPAddress, roomId); + const userUuid = await jwtTokenManager.getUserUuidFromToken(token, IPAddress, roomId); + let memberTags: string[] = []; let memberTextures: CharacterTexture[] = []; const room = await socketManager.getOrCreateRoom(roomId); diff --git a/pusher/src/Services/JWTTokenManager.ts b/pusher/src/Services/JWTTokenManager.ts index ca692b77..68b07735 100644 --- a/pusher/src/Services/JWTTokenManager.ts +++ b/pusher/src/Services/JWTTokenManager.ts @@ -10,7 +10,7 @@ class JWTTokenManager { return Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '200d'}); //todo: add a mechanic to refresh or recreate token } - public async getUserUuidFromToken(token: unknown): Promise { + public async getUserUuidFromToken(token: unknown, ipAddress?: string, room?: string): Promise { if (!token) { throw new Error('An authentication error happened, a user tried to connect without a token.'); @@ -50,14 +50,22 @@ class JWTTokenManager { if (ADMIN_API_URL) { //verify user in admin - adminApi.fetchCheckUserByToken(tokenInterface.userUuid).then(() => { - resolve(tokenInterface.userUuid); - }).catch((err) => { - //anonymous user - if (err.response && err.response.status && err.response.status === 404) { + let promise = new Promise((resolve) => resolve()); + if(ipAddress && room) { + promise = this.verifyBanUser(tokenInterface.userUuid, ipAddress, room); + } + promise.then(() => { + adminApi.fetchCheckUserByToken(tokenInterface.userUuid).then(() => { resolve(tokenInterface.userUuid); - return; - } + }).catch((err) => { + //anonymous user + if (err.response && err.response.status && err.response.status === 404) { + resolve(tokenInterface.userUuid); + return; + } + reject(err); + }); + }).catch((err) => { reject(err); }); } else { @@ -67,12 +75,13 @@ class JWTTokenManager { }); } - public async verifyBanUser(userUuid: string, ipAddress: string, room: string): Promise { + private verifyBanUser(userUuid: string, ipAddress: string, room: string): Promise { room = room.split('/').join('_'); return adminApi.verifyBanUser(userUuid, ipAddress, room).then((data: AdminBannedData) => { if (data && data.is_banned) { throw new Error('User was banned'); } + return data; }).catch((err) => { throw err; }); From 0bbaef0cb5288504ce95d44f29ec2d2910cf9833 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sun, 17 Jan 2021 03:07:46 +0100 Subject: [PATCH 04/17] Fix send message and ban message --- back/src/RoomManager.ts | 20 +++-- back/src/Services/SocketManager.ts | 49 +++++++++---- messages/protos/messages.proto | 9 +++ pusher/src/Controller/IoSocketController.ts | 17 ++--- pusher/src/Services/JWTTokenManager.ts | 4 +- pusher/src/Services/SocketManager.ts | 81 ++++++++++----------- 6 files changed, 101 insertions(+), 79 deletions(-) diff --git a/back/src/RoomManager.ts b/back/src/RoomManager.ts index 3c038998..ca7198fd 100644 --- a/back/src/RoomManager.ts +++ b/back/src/RoomManager.ts @@ -2,25 +2,21 @@ import {IRoomManagerServer} from "./Messages/generated/messages_grpc_pb"; import { AdminGlobalMessage, AdminMessage, - AdminPusherToBackMessage, BanMessage, - ClientToServerMessage, EmptyMessage, + AdminPusherToBackMessage, + EmptyMessage, ItemEventMessage, JoinRoomMessage, PlayGlobalMessage, PusherToBackMessage, QueryJitsiJwtMessage, - ReportPlayerMessage, - RoomJoinedMessage, ServerToAdminClientMessage, ServerToClientMessage, SilentMessage, UserMovesMessage, - ViewportMessage, WebRtcSignalToServerMessage, ZoneMessage } from "./Messages/generated/messages_pb"; -import grpc, {sendUnaryData, ServerDuplexStream, ServerUnaryCall, ServerWritableStream} from "grpc"; -import {Empty} from "google-protobuf/google/protobuf/empty_pb"; +import {sendUnaryData, ServerDuplexStream, ServerUnaryCall, ServerWritableStream} from "grpc"; import {socketManager} from "./Services/SocketManager"; import {emitError} from "./Services/MessageHelpers"; import {User, UserSocket} from "./Model/User"; @@ -74,6 +70,16 @@ const roomManager: IRoomManagerServer = { socketManager.handleReportMessage(client, message.getReportplayermessage() as ReportPlayerMessage);*/ } else if (message.hasQueryjitsijwtmessage()){ socketManager.handleQueryJitsiJwtMessage(user, message.getQueryjitsijwtmessage() as QueryJitsiJwtMessage); + }else if (message.hasSendusermessage()) { + const sendUserMessage = message.getSendusermessage(); + if(sendUserMessage !== undefined) { + socketManager.handlerSendUserMessage(user, sendUserMessage); + } + }else if (message.hasBanusermessage()) { + const banUserMessage = message.getBanusermessage(); + if(banUserMessage !== undefined) { + socketManager.handlerBanUserMessage(room, user, banUserMessage); + } } else { throw new Error('Unhandled message type'); } diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index bfc43050..c90b51cf 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -1,24 +1,16 @@ import {GameRoom} from "../Model/GameRoom"; import {CharacterLayer} from "_Model/Websocket/CharacterLayer"; import { - GroupDeleteMessage, - GroupUpdateMessage, ItemEventMessage, ItemStateMessage, PlayGlobalMessage, PointMessage, - PositionMessage, RoomJoinedMessage, ServerToClientMessage, - SetPlayerDetailsMessage, SilentMessage, SubMessage, - ReportPlayerMessage, - UserJoinedMessage, - UserLeftMessage, UserMovedMessage, UserMovesMessage, - ViewportMessage, WebRtcDisconnectMessage, WebRtcSignalToClientMessage, WebRtcSignalToServerMessage, @@ -28,24 +20,23 @@ import { SendUserMessage, JoinRoomMessage, Zone as ProtoZone, - BatchMessage, BatchToPusherMessage, SubToPusherMessage, - UserJoinedZoneMessage, GroupUpdateZoneMessage, GroupLeftZoneMessage, UserLeftZoneMessage, AdminMessage, BanMessage + UserJoinedZoneMessage, GroupUpdateZoneMessage, GroupLeftZoneMessage, UserLeftZoneMessage, BanUserMessage } from "../Messages/generated/messages_pb"; import {User, UserSocket} from "../Model/User"; import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils"; import {Group} from "../Model/Group"; import {cpuTracker} from "./CpuTracker"; -import {ADMIN_API_URL, GROUP_RADIUS, JITSI_ISS, MINIMUM_DISTANCE, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable"; +import {GROUP_RADIUS, JITSI_ISS, MINIMUM_DISTANCE, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable"; import {Movable} from "../Model/Movable"; import {PositionInterface} from "../Model/PositionInterface"; -import {adminApi, CharacterTexture, FetchMemberDataByUuidResponse} from "./AdminApi"; +import {adminApi, CharacterTexture} from "./AdminApi"; import Jwt from "jsonwebtoken"; import {JITSI_URL} from "../Enum/EnvironmentVariable"; import {clientEventsEmitter} from "./ClientEventsEmitter"; import {gaugeManager} from "./GaugeManager"; -import {AdminSocket, ZoneSocket} from "../RoomManager"; +import {ZoneSocket} from "../RoomManager"; import {Zone} from "_Model/Zone"; import Debug from "debug"; import {Admin} from "_Model/Admin"; @@ -119,7 +110,7 @@ export class SocketManager { //const things = room.setViewport(client, viewport); const roomJoinedMessage = new RoomJoinedMessage(); - + roomJoinedMessage.setTagList(joinRoomMessage.getTagList()); /*for (const thing of things) { if (thing instanceof User) { const player: ExSocketInterface|undefined = this.sockets.get(thing.id); @@ -626,6 +617,33 @@ export class SocketManager { user.socket.write(serverToClientMessage); } + public handlerSendUserMessage(user: User, sendUserMessageToSend: SendUserMessage){ + const sendUserMessage = new SendUserMessage(); + sendUserMessage.setMessage(sendUserMessageToSend.getMessage()); + sendUserMessage.setType(sendUserMessageToSend.getType()); + + const serverToClientMessage = new ServerToClientMessage(); + serverToClientMessage.setSendusermessage(sendUserMessage); + user.socket.write(serverToClientMessage); + } + + public handlerBanUserMessage(room: GameRoom, user: User, banUserMessageToSend: BanUserMessage){ + const banUserMessage = new BanUserMessage(); + banUserMessage.setMessage(banUserMessageToSend.getMessage()); + banUserMessage.setType(banUserMessageToSend.getType()); + + const serverToClientMessage = new ServerToClientMessage(); + serverToClientMessage.setSendusermessage(banUserMessage); + user.socket.write(serverToClientMessage); + + setTimeout(() => { + // Let's leave the room now. + room.leave(user); + // Let's close the connection when the user is banned. + user.socket.end(); + }, 10000); + } + /** * Merges the characterLayers received from the front (as an array of string) with the custom textures from the back. */ @@ -748,7 +766,7 @@ export class SocketManager { recipient.socket.write(subToPusherMessage); } - public banUser(roomId: string, recipientUuid: string): void { + public banUser(roomId: string, recipientUuid: string, message: string): void { const room = this.rooms.get(roomId); if (!room) { console.error("In banUser, could not find room with id '" + roomId + "'. Maybe the room was closed a few milliseconds ago and there was a race condition?"); @@ -765,6 +783,7 @@ export class SocketManager { room.leave(recipient); const sendUserMessage = new SendUserMessage(); + sendUserMessage.setMessage(message); sendUserMessage.setType('banned'); const subToPusherMessage = new SubToPusherMessage(); diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 0e92f381..64f18f13 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -193,6 +193,11 @@ message SendUserMessage{ string message = 2; } +message BanUserMessage{ + string type = 1; + string message = 2; +} + message ServerToClientMessage { oneof message { BatchMessage batchMessage = 1; @@ -207,6 +212,7 @@ message ServerToClientMessage { TeleportMessageMessage teleportMessageMessage = 10; SendJitsiJwtMessage sendJitsiJwtMessage = 11; SendUserMessage sendUserMessage = 12; + BanUserMessage banUserMessage = 13; } } @@ -273,6 +279,8 @@ message PusherToBackMessage { StopGlobalMessage stopGlobalMessage = 9; ReportPlayerMessage reportPlayerMessage = 10; QueryJitsiJwtMessage queryJitsiJwtMessage = 11; + SendUserMessage sendUserMessage = 12; + BanUserMessage banUserMessage = 13; } } @@ -289,6 +297,7 @@ message SubToPusherMessage { UserLeftZoneMessage userLeftZoneMessage = 5; ItemEventMessage itemEventMessage = 6; SendUserMessage sendUserMessage = 7; + BanUserMessage banUserMessage = 8; } } diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 63019b7d..a43f43ba 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -91,18 +91,11 @@ export class IoSocketController { if(message.event === 'user-message') { const messageToEmit = (message.message as { message: string, type: string, userUuid: string }); - switch (message.message.type) { - case 'ban': { - socketManager.emitSendUserMessage(messageToEmit.userUuid, messageToEmit.message, roomId); - break; - } - case 'banned': { - socketManager.emitBan(messageToEmit.userUuid, messageToEmit.message, roomId); - break; - } - default: { - break; - } + if(messageToEmit.type === 'banned'){ + socketManager.emitBan(messageToEmit.userUuid, messageToEmit.message, messageToEmit.type); + } + if(messageToEmit.type === 'ban') { + socketManager.emitSendUserMessage(messageToEmit.userUuid, messageToEmit.message, messageToEmit.type); } } }catch (err) { diff --git a/pusher/src/Services/JWTTokenManager.ts b/pusher/src/Services/JWTTokenManager.ts index 68b07735..6605ec4e 100644 --- a/pusher/src/Services/JWTTokenManager.ts +++ b/pusher/src/Services/JWTTokenManager.ts @@ -76,8 +76,8 @@ class JWTTokenManager { } private verifyBanUser(userUuid: string, ipAddress: string, room: string): Promise { - room = room.split('/').join('_'); - return adminApi.verifyBanUser(userUuid, ipAddress, room).then((data: AdminBannedData) => { + const world = room.split('/')[1]; //check by world + return adminApi.verifyBanUser(userUuid, ipAddress, world).then((data: AdminBannedData) => { if (data && data.is_banned) { throw new Error('User was banned'); } diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index df944b9e..ff5d25cf 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -2,11 +2,8 @@ import {PusherRoom} from "../Model/PusherRoom"; import {CharacterLayer, ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; import { GroupDeleteMessage, - GroupUpdateMessage, ItemEventMessage, - ItemStateMessage, PlayGlobalMessage, - PointMessage, PositionMessage, RoomJoinedMessage, ServerToClientMessage, @@ -14,23 +11,18 @@ import { SilentMessage, SubMessage, ReportPlayerMessage, - UserJoinedMessage, UserLeftMessage, - UserMovedMessage, UserMovesMessage, ViewportMessage, - WebRtcDisconnectMessage, - WebRtcSignalToClientMessage, WebRtcSignalToServerMessage, - WebRtcStartMessage, QueryJitsiJwtMessage, SendJitsiJwtMessage, - SendUserMessage, JoinRoomMessage, CharacterLayerMessage, PusherToBackMessage, AdminPusherToBackMessage, - ServerToAdminClientMessage, AdminMessage, BanMessage + ServerToAdminClientMessage, + AdminMessage, SendUserMessage, BanUserMessage } from "../Messages/generated/messages_pb"; import {PointInterface} from "../Model/Websocket/PointInterface"; import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils"; @@ -142,7 +134,6 @@ export class SocketManager implements ZoneEventListener { } async handleJoinRoom(client: ExSocketInterface): Promise { - const position = client.position; const viewport = client.viewport; try { @@ -152,6 +143,7 @@ export class SocketManager implements ZoneEventListener { joinRoomMessage.setRoomid(client.roomId); joinRoomMessage.setName(client.name); joinRoomMessage.setPositionmessage(ProtobufUtils.toPositionMessage(client.position)); + joinRoomMessage.setTagList(client.tags); for (const characterLayer of client.characterLayers) { const characterLayerMessage = new CharacterLayerMessage(); characterLayerMessage.setName(characterLayer.name); @@ -538,51 +530,54 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } - public async emitSendUserMessage(userUuid: string, message: string, roomId: string): Promise { + public async emitSendUserMessage(userUuid: string, message: string, type: string): Promise { + const client = this.searchClientByUuid(userUuid); + if(!client){ + throw Error('client not found'); + } - const backConnection = await apiClientRepository.getClient(roomId); - - const adminMessage = new AdminMessage(); - adminMessage.setRecipientuuid(userUuid); + const adminMessage = new SendUserMessage(); adminMessage.setMessage(message); - adminMessage.setRoomid(roomId); + adminMessage.setType(type); + const pusherToBackMessage = new PusherToBackMessage(); + pusherToBackMessage.setSendusermessage(adminMessage); + client.backConnection.write(pusherToBackMessage); + /*const backConnection = await apiClientRepository.getClient(client.roomId); + const adminMessage = new AdminMessage(); + adminMessage.setMessage(message); + adminMessage.setRoomid(client.roomId); + adminMessage.setRecipientuuid(client.userUuid); backConnection.sendAdminMessage(adminMessage, (error) => { if (error !== null) { console.error('Error while sending admin message', error); } - }); -/* - const socket = this.searchClientByUuid(messageToSend.userUuid); - if(!socket){ - throw 'socket was not found'; - } - - const sendUserMessage = new SendUserMessage(); - sendUserMessage.setMessage(messageToSend.message); - sendUserMessage.setType(messageToSend.type); - - const serverToClientMessage = new ServerToClientMessage(); - serverToClientMessage.setSendusermessage(sendUserMessage); - - if (!socket.disconnecting) { - socket.send(serverToClientMessage.serializeBinary().buffer, true); - } - return socket;*/ + });*/ } - public async emitBan(userUuid: string, message: string, roomId: string): Promise { - const backConnection = await apiClientRepository.getClient(roomId); + public async emitBan(userUuid: string, message: string, type: string): Promise { + const client = this.searchClientByUuid(userUuid); + if(!client){ + throw Error('client not found'); + } - const banMessage = new BanMessage(); - banMessage.setRecipientuuid(userUuid); - banMessage.setRoomid(roomId); + const banUserMessage = new BanUserMessage(); + banUserMessage.setMessage(message); + banUserMessage.setType(type); + const pusherToBackMessage = new PusherToBackMessage(); + pusherToBackMessage.setBanusermessage(banUserMessage); + client.backConnection.write(pusherToBackMessage); - backConnection.ban(banMessage, (error) => { + /*const backConnection = await apiClientRepository.getClient(client.roomId); + const adminMessage = new AdminMessage(); + adminMessage.setMessage(message); + adminMessage.setRoomid(client.roomId); + adminMessage.setRecipientuuid(client.userUuid); + backConnection.sendAdminMessage(adminMessage, (error) => { if (error !== null) { - console.error('Error while sending ban message', error); + console.error('Error while sending admin message', error); } - }); + });*/ } /** From adca51f6dedb0a4da629c63f497e7f92e046158e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 17 Jan 2021 20:34:35 +0100 Subject: [PATCH 05/17] Replacing FourOFourScene with more generic ErrorScene --- front/src/Connexion/Room.ts | 5 +- front/src/Phaser/Game/GameScene.ts | 14 +-- front/src/Phaser/Login/EntryScene.ts | 9 +- front/src/Phaser/Reconnecting/ErrorScene.ts | 98 +++++++++++++++++++ .../src/Phaser/Reconnecting/FourOFourScene.ts | 68 ------------- front/src/index.ts | 4 +- 6 files changed, 114 insertions(+), 84 deletions(-) create mode 100644 front/src/Phaser/Reconnecting/ErrorScene.ts delete mode 100644 front/src/Phaser/Reconnecting/FourOFourScene.ts diff --git a/front/src/Connexion/Room.ts b/front/src/Connexion/Room.ts index d9bfe905..72c3b42e 100644 --- a/front/src/Connexion/Room.ts +++ b/front/src/Connexion/Room.ts @@ -25,7 +25,7 @@ export class Room { this.id = this.id.substr(0, indexOfHash); } } - + public static getIdFromIdentifier(identifier: string, baseUrl: string, currentInstance: string): {roomId: string, hash: string} { let roomId = ''; let hash = ''; @@ -72,8 +72,9 @@ export class Room { console.log('Map ', this.id, ' resolves to URL ', data.mapUrl); resolve(data.mapUrl); return; + }).catch((reason) => { + reject(reason); }); - } }); } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d25c2893..c2cb0950 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -45,7 +45,6 @@ import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR; import {GameMap} from "./GameMap"; import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; import {mediaManager} from "../../WebRtc/MediaManager"; -import {FourOFourSceneName} from "../Reconnecting/FourOFourScene"; import {ItemFactoryInterface} from "../Items/ItemFactoryInterface"; import {ActionableItem} from "../Items/ActionableItem"; import {UserInputManager} from "../UserInput/UserInputManager"; @@ -67,6 +66,7 @@ import {OpenChatIcon, openChatIconName} from "../Components/OpenChatIcon"; import {SelectCharacterScene, SelectCharacterSceneName} from "../Login/SelectCharacterScene"; import {TextureError} from "../../Exception/TextureError"; import {addLoader} from "../Components/Loader"; +import {ErrorSceneName} from "../Reconnecting/ErrorScene"; export interface GameSceneInitInterface { initPosition: PointInterface|null, @@ -185,8 +185,10 @@ export class GameScene extends ResizableScene implements CenterListener { this.load.image(openChatIconName, 'resources/objects/talk.png'); this.load.on(FILE_LOAD_ERROR, (file: {src: string}) => { - this.scene.start(FourOFourSceneName, { - file: file.src + this.scene.start(ErrorSceneName, { + title: 'Network error', + subTitle: 'An error occurred while loading resource:', + message: file.src }); }); this.load.on('filecomplete-tilemapJSON-'+this.MapUrlFile, (key: string, type: string, data: unknown) => { @@ -375,7 +377,7 @@ export class GameScene extends ResizableScene implements CenterListener { //notify game manager can to create currentUser in map this.createCurrentPlayer(); this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted - + this.initCamera(); this.initCirclesCanvas(); @@ -1039,7 +1041,7 @@ export class GameScene extends ResizableScene implements CenterListener { event: addPlayerData }); } - + private doAddPlayer(addPlayerData : AddPlayerInterface): void { //check if exist player, if exist, move position if(this.MapPlayersByKey.has(addPlayerData.userId)){ @@ -1192,7 +1194,7 @@ export class GameScene extends ResizableScene implements CenterListener { // Let's put this in Game coordinates by applying the zoom level: xCenter /= ZOOM_LEVEL * RESOLUTION; yCenter /= ZOOM_LEVEL * RESOLUTION; - + this.cameras.main.startFollow(this.CurrentPlayer, true, 1, 1, xCenter - this.game.renderer.width / 2, yCenter - this.game.renderer.height / 2); } diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index c7527349..fc551375 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -1,7 +1,7 @@ import {gameManager} from "../Game/GameManager"; import {Scene} from "phaser"; -import {LoginSceneName} from "./LoginScene"; -import {FourOFourSceneName} from "../Reconnecting/FourOFourScene"; +import {handleAxiosError} from "../../Network/axios"; +import {ErrorScene} from "../Reconnecting/ErrorScene"; export const EntrySceneName = "EntryScene"; @@ -20,10 +20,7 @@ export class EntryScene extends Scene { gameManager.init(this.scene).then((nextSceneName) => { this.scene.start(nextSceneName); }).catch((err) => { - console.error(err) - this.scene.start(FourOFourSceneName, { - url: window.location.pathname.toString() - }); + ErrorScene.showError(err, this.scene); }); } } diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts new file mode 100644 index 00000000..8253c5e8 --- /dev/null +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -0,0 +1,98 @@ +import {TextField} from "../Components/TextField"; +import Image = Phaser.GameObjects.Image; +import Sprite = Phaser.GameObjects.Sprite; +import Text = Phaser.GameObjects.Text; +import ScenePlugin = Phaser.Scenes.ScenePlugin; + +export const ErrorSceneName = "ErrorScene"; +enum Textures { + icon = "icon", + mainFont = "main_font" +} + +export class ErrorScene extends Phaser.Scene { + private titleField!: TextField; + private subTitleField!: TextField; + private messageField!: Text; + private logo!: Image; + private cat!: Sprite; + private title!: string; + private subTitle!: string; + private message!: string; + + constructor() { + super({ + key: ErrorSceneName + }); + } + + init({ title, subTitle, message }: { title?: string, subTitle?: string, message?: string }) { + this.title = title ? title : ''; + this.subTitle = subTitle ? subTitle : ''; + this.message = message ? message : ''; + } + + preload() { + this.load.image(Textures.icon, "resources/logos/tcm_full.png"); + // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap + this.load.bitmapFont(Textures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); + this.load.spritesheet( + 'cat', + 'resources/characters/pipoya/Cat 01-1.png', + {frameWidth: 32, frameHeight: 32} + ); + } + + create() { + this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, Textures.icon); + this.add.existing(this.logo); + + this.titleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2, this.title); + + this.subTitleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, this.subTitle); + + this.messageField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, this.message, { fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif', fontSize: '10px' }); + this.messageField.setOrigin(0.5, 0.5); + + this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6); + this.cat.flipY=true; + } + + /** + * Displays the error page, with an error message matching the "error" parameters passed in. + */ + public static showError(error: any, scene: ScenePlugin): void { + console.error(error); + + if (typeof error === 'string' || error instanceof String) { + scene.start(ErrorSceneName, { + title: 'An error occurred', + subTitle: error + }); + } else if (error.response) { + // Axios HTTP error + // client received an error response (5xx, 4xx) + scene.start(ErrorSceneName, { + title: 'HTTP ' + error.response.status + ' - ' + error.response.statusText, + subTitle: 'An error occurred while accessing URL:', + message: error.response.config.url + }); + } else if (error.request) { + // Axios HTTP error + // client never received a response, or request never left + scene.start(ErrorSceneName, { + title: 'Network error', + subTitle: error.message + }); + } else if (error instanceof Error) { + // Error + scene.start(ErrorSceneName, { + title: 'An error occurred', + subTitle: error.name, + message: error.message + }); + } else { + throw error; + } + } +} diff --git a/front/src/Phaser/Reconnecting/FourOFourScene.ts b/front/src/Phaser/Reconnecting/FourOFourScene.ts deleted file mode 100644 index 36106796..00000000 --- a/front/src/Phaser/Reconnecting/FourOFourScene.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {TextField} from "../Components/TextField"; -import Image = Phaser.GameObjects.Image; -import Sprite = Phaser.GameObjects.Sprite; -import Text = Phaser.GameObjects.Text; - -export const FourOFourSceneName = "FourOFourScene"; -enum Textures { - icon = "icon", - mainFont = "main_font" -} - -export class FourOFourScene extends Phaser.Scene { - private mapNotFoundField!: TextField; - private couldNotFindField!: TextField; - private fileNameField!: Text; - private logo!: Image; - private cat!: Sprite; - private file: string|undefined; - private url: string|undefined; - - constructor() { - super({ - key: FourOFourSceneName - }); - } - - init({ file, url }: { file?: string, url?: string }) { - this.file = file; - this.url = url; - } - - preload() { - this.load.image(Textures.icon, "resources/logos/tcm_full.png"); - // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap - this.load.bitmapFont(Textures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); - this.load.spritesheet( - 'cat', - 'resources/characters/pipoya/Cat 01-1.png', - {frameWidth: 32, frameHeight: 32} - ); - } - - create() { - this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, Textures.icon); - this.add.existing(this.logo); - - this.mapNotFoundField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2, "404 - File not found"); - - let text: string = ''; - if (this.file !== undefined) { - text = "Could not load map" - } - if (this.url !== undefined) { - text = "Invalid URL" - } - - this.couldNotFindField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, text); - - const url = this.file ? this.file : this.url; - if (url !== undefined) { - this.fileNameField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, url, { fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif', fontSize: '10px' }); - this.fileNameField.setOrigin(0.5, 0.5); - } - - this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6); - this.cat.flipY=true; - } -} diff --git a/front/src/index.ts b/front/src/index.ts index abca6036..acf66cf8 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -6,7 +6,6 @@ import {LoginScene} from "./Phaser/Login/LoginScene"; import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene"; import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene"; import {EnableCameraScene} from "./Phaser/Login/EnableCameraScene"; -import {FourOFourScene} from "./Phaser/Reconnecting/FourOFourScene"; import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer; import {OutlinePipeline} from "./Phaser/Shaders/OutlinePipeline"; import {CustomizeScene} from "./Phaser/Login/CustomizeScene"; @@ -15,6 +14,7 @@ import {EntryScene} from "./Phaser/Login/EntryScene"; import {coWebsiteManager} from "./WebRtc/CoWebsiteManager"; import {MenuScene} from "./Phaser/Menu/MenuScene"; import {localUserStore} from "./Connexion/LocalUserStore"; +import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene"; // Load Jitsi if the environment variable is set. if (JITSI_URL) { @@ -59,7 +59,7 @@ const config: GameConfig = { width: width / RESOLUTION, height: height / RESOLUTION, parent: "game", - scene: [EntryScene, LoginScene, SelectCharacterScene, EnableCameraScene, ReconnectingScene, FourOFourScene, CustomizeScene, MenuScene], + scene: [EntryScene, LoginScene, SelectCharacterScene, EnableCameraScene, ReconnectingScene, ErrorScene, CustomizeScene, MenuScene], zoom: RESOLUTION, fps: fps, dom: { From a5aa9b6cf9bdef260b7456ae34b2a69ca1b491bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 17 Jan 2021 20:34:51 +0100 Subject: [PATCH 06/17] /map now returns the correct error status code --- pusher/src/Controller/MapController.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pusher/src/Controller/MapController.ts b/pusher/src/Controller/MapController.ts index c111ba64..5ad7bc8e 100644 --- a/pusher/src/Controller/MapController.ts +++ b/pusher/src/Controller/MapController.ts @@ -59,10 +59,15 @@ export class MapController extends BaseController{ this.addCorsHeaders(res); res.end(JSON.stringify(mapDetails)); } catch (e) { - console.error(e.message || e); - res.writeStatus("500 Internal Server Error") - this.addCorsHeaders(res); - res.end("An error occurred"); + if (e.response) { + res.writeStatus(e.response.status+" "+e.response.statusText); + this.addCorsHeaders(res); + res.end("An error occurred: "+e.response.status+" "+e.response.statusText); + } else { + res.writeStatus("500 Internal Server Error") + this.addCorsHeaders(res); + res.end("An error occurred"); + } } })(); From 48c3f951bf5cada188f70185837875e9679ce2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 17 Jan 2021 20:42:33 +0100 Subject: [PATCH 07/17] Correctly forwarding HTTP error status code from admin to front --- pusher/src/Controller/AuthenticateController.ts | 5 +---- pusher/src/Controller/BaseController.ts | 16 ++++++++++++++++ pusher/src/Controller/MapController.ts | 10 +--------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index bf68768d..f82974b6 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -60,10 +60,7 @@ export class AuthenticateController extends BaseController { })); } catch (e) { - console.error("An error happened", e) - res.writeStatus(e.status || "500 Internal Server Error"); - this.addCorsHeaders(res); - res.end('An error happened'); + this.errorToResponse(e, res); } diff --git a/pusher/src/Controller/BaseController.ts b/pusher/src/Controller/BaseController.ts index 0b744082..2096496d 100644 --- a/pusher/src/Controller/BaseController.ts +++ b/pusher/src/Controller/BaseController.ts @@ -8,4 +8,20 @@ export class BaseController { res.writeHeader('access-control-allow-methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); res.writeHeader('access-control-allow-origin', '*'); } + + /** + * Turns any exception into a HTTP response (and logs the error) + */ + protected errorToResponse(e: any, res: HttpResponse): void { + console.error("An error happened", e); + if (e.response) { + res.writeStatus(e.response.status+" "+e.response.statusText); + this.addCorsHeaders(res); + res.end("An error occurred: "+e.response.status+" "+e.response.statusText); + } else { + res.writeStatus("500 Internal Server Error") + this.addCorsHeaders(res); + res.end("An error occurred"); + } + } } diff --git a/pusher/src/Controller/MapController.ts b/pusher/src/Controller/MapController.ts index 5ad7bc8e..1ce04265 100644 --- a/pusher/src/Controller/MapController.ts +++ b/pusher/src/Controller/MapController.ts @@ -59,15 +59,7 @@ export class MapController extends BaseController{ this.addCorsHeaders(res); res.end(JSON.stringify(mapDetails)); } catch (e) { - if (e.response) { - res.writeStatus(e.response.status+" "+e.response.statusText); - this.addCorsHeaders(res); - res.end("An error occurred: "+e.response.status+" "+e.response.statusText); - } else { - res.writeStatus("500 Internal Server Error") - this.addCorsHeaders(res); - res.end("An error occurred"); - } + this.errorToResponse(e, res); } })(); From 4234b3891083c7f742ecebc27154e91aea612a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 17 Jan 2021 22:40:54 +0100 Subject: [PATCH 08/17] Better error message in case of 404 --- front/src/Phaser/Login/EntryScene.ts | 8 ++++-- front/src/Phaser/Reconnecting/ErrorScene.ts | 27 ++++++++++++++++++--- front/src/Phaser/Reconnecting/WAError.ts | 26 ++++++++++++++++++++ pusher/src/Services/SocketManager.ts | 3 ++- 4 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 front/src/Phaser/Reconnecting/WAError.ts diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index fc551375..75ee0272 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -1,7 +1,7 @@ import {gameManager} from "../Game/GameManager"; import {Scene} from "phaser"; -import {handleAxiosError} from "../../Network/axios"; import {ErrorScene} from "../Reconnecting/ErrorScene"; +import {WAError} from "../Reconnecting/WAError"; export const EntrySceneName = "EntryScene"; @@ -20,7 +20,11 @@ export class EntryScene extends Scene { gameManager.init(this.scene).then((nextSceneName) => { this.scene.start(nextSceneName); }).catch((err) => { - ErrorScene.showError(err, this.scene); + if (err.response && err.response.status == 404) { + ErrorScene.showError(new WAError('Page Not Found', 'Could not find map', window.location.pathname), this.scene); + } else { + ErrorScene.showError(err, this.scene); + } }); } } diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts index 8253c5e8..d7fc2ab7 100644 --- a/front/src/Phaser/Reconnecting/ErrorScene.ts +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -3,6 +3,7 @@ import Image = Phaser.GameObjects.Image; import Sprite = Phaser.GameObjects.Sprite; import Text = Phaser.GameObjects.Text; import ScenePlugin = Phaser.Scenes.ScenePlugin; +import {WAError} from "./WAError"; export const ErrorSceneName = "ErrorScene"; enum Textures { @@ -26,7 +27,7 @@ export class ErrorScene extends Phaser.Scene { }); } - init({ title, subTitle, message }: { title?: string, subTitle?: string, message?: string }) { + init({title, subTitle, message}: { title?: string, subTitle?: string, message?: string }) { this.title = title ? title : ''; this.subTitle = subTitle ? subTitle : ''; this.message = message ? message : ''; @@ -51,11 +52,14 @@ export class ErrorScene extends Phaser.Scene { this.subTitleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, this.subTitle); - this.messageField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, this.message, { fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif', fontSize: '10px' }); + this.messageField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, this.message, { + fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif', + fontSize: '10px' + }); this.messageField.setOrigin(0.5, 0.5); this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6); - this.cat.flipY=true; + this.cat.flipY = true; } /** @@ -69,6 +73,12 @@ 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 (error.response) { // Axios HTTP error // client received an error response (5xx, 4xx) @@ -95,4 +105,15 @@ export class ErrorScene extends Phaser.Scene { throw error; } } + + /** + * Displays the error page, with an error message matching the "error" parameters passed in. + */ + public static startErrorPage(title: string, subTitle: string, message: string, scene: ScenePlugin): void { + scene.start(ErrorSceneName, { + title, + subTitle, + message + }); + } } diff --git a/front/src/Phaser/Reconnecting/WAError.ts b/front/src/Phaser/Reconnecting/WAError.ts new file mode 100644 index 00000000..cdc433b6 --- /dev/null +++ b/front/src/Phaser/Reconnecting/WAError.ts @@ -0,0 +1,26 @@ +export class WAError extends Error { + private _title: string; + private _subTitle: string; + private _details: string; + + constructor (title: string, subTitle: string, details: string) { + super(title+' - '+subTitle+' - '+details); + this._title = title; + this._subTitle = subTitle; + this._details = details; + // Set the prototype explicitly. + Object.setPrototypeOf (this, WAError.prototype); + } + + get title(): string { + return this._title; + } + + get subTitle(): string { + return this._subTitle; + } + + get details(): string { + return this._details; + } +} diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index ff5d25cf..f5915ddb 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -22,7 +22,8 @@ import { PusherToBackMessage, AdminPusherToBackMessage, ServerToAdminClientMessage, - AdminMessage, SendUserMessage, BanUserMessage + SendUserMessage, + BanUserMessage } from "../Messages/generated/messages_pb"; import {PointInterface} from "../Model/Websocket/PointInterface"; import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils"; From b1d4af005efb4326f50f460c0f6c5af10608e84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 17 Jan 2021 22:44:22 +0100 Subject: [PATCH 09/17] Adding missing use statement --- back/src/RoomManager.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/back/src/RoomManager.ts b/back/src/RoomManager.ts index ca7198fd..b6846f3d 100644 --- a/back/src/RoomManager.ts +++ b/back/src/RoomManager.ts @@ -3,6 +3,7 @@ import { AdminGlobalMessage, AdminMessage, AdminPusherToBackMessage, + BanMessage, EmptyMessage, ItemEventMessage, JoinRoomMessage, From d1222e444093672fd32e17c212920f1a6a3c8b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 15:07:40 +0100 Subject: [PATCH 10/17] Refactoring admin messages --- back/src/Model/Admin.ts | 20 ++++++++++++++++---- back/src/Model/GameRoom.ts | 2 +- back/src/RoomManager.ts | 4 ++-- messages/protos/messages.proto | 14 ++++++++++++-- pusher/src/Services/SocketManager.ts | 27 ++++++++++++++++++++------- 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/back/src/Model/Admin.ts b/back/src/Model/Admin.ts index 53757e96..9d9c85ce 100644 --- a/back/src/Model/Admin.ts +++ b/back/src/Model/Admin.ts @@ -9,7 +9,7 @@ import { PusherToBackMessage, ServerToAdminClientMessage, ServerToClientMessage, - SubMessage + SubMessage, UserJoinedRoomMessage, UserLeftRoomMessage } from "../Messages/generated/messages_pb"; import {CharacterLayer} from "_Model/Websocket/CharacterLayer"; import {AdminSocket} from "../RoomManager"; @@ -23,13 +23,25 @@ export class Admin { public sendUserJoin(uuid: string, name: string, ip: string): void { let serverToAdminClientMessage = new ServerToAdminClientMessage(); - serverToAdminClientMessage = serverToAdminClientMessage.setUseruuidnamejoinedroom(uuid+';'+name+';'+ip) + + let userJoinedRoomMessage = new UserJoinedRoomMessage(); + userJoinedRoomMessage.setUuid(uuid); + userJoinedRoomMessage.setName(name); + userJoinedRoomMessage.setIpaddress(ip); + + serverToAdminClientMessage.setUserjoinedroom(userJoinedRoomMessage); + this.socket.write(serverToAdminClientMessage); } - public sendUserLeft(uuid: string, name: string, ip: string): void { + public sendUserLeft(uuid: string/*, name: string, ip: string*/): void { let serverToAdminClientMessage = new ServerToAdminClientMessage(); - serverToAdminClientMessage = serverToAdminClientMessage.setUseruuidnameleftroom(uuid+';'+name+';'+ip); + + let userLeftRoomMessage = new UserLeftRoomMessage(); + userLeftRoomMessage.setUuid(uuid); + + serverToAdminClientMessage.setUserleftroom(userLeftRoomMessage); + this.socket.write(serverToAdminClientMessage); } } diff --git a/back/src/Model/GameRoom.ts b/back/src/Model/GameRoom.ts index 8a57ee99..41c215ad 100644 --- a/back/src/Model/GameRoom.ts +++ b/back/src/Model/GameRoom.ts @@ -145,7 +145,7 @@ export class GameRoom { // Notify admins for (const admin of this.admins) { - admin.sendUserLeft(user.uuid, user.name, user.IPAddress); + admin.sendUserLeft(user.uuid/*, user.name, user.IPAddress*/); } } diff --git a/back/src/RoomManager.ts b/back/src/RoomManager.ts index b6846f3d..b6a82850 100644 --- a/back/src/RoomManager.ts +++ b/back/src/RoomManager.ts @@ -203,8 +203,8 @@ const roomManager: IRoomManagerServer = { callback(null, new EmptyMessage()); }, ban(call: ServerUnaryCall, callback: sendUnaryData): void { - - socketManager.banUser(call.request.getRoomid(), call.request.getRecipientuuid()); + // FIXME Work in progress + socketManager.banUser(call.request.getRoomid(), call.request.getRecipientuuid(), 'foo bar TODO change this'); callback(null, new EmptyMessage()); }, diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 64f18f13..39f575be 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -316,10 +316,20 @@ message ServerToAdminClientMessage { repeated SubToAdminPusherMessage payload = 2; }*/ +message UserJoinedRoomMessage { + string uuid = 1; + string ipAddress = 2; + string name = 3; +} + +message UserLeftRoomMessage { + string uuid = 1; +} + message ServerToAdminClientMessage { oneof message { - string userUuidNameJoinedRoom = 1; - string userUuidNameLeftRoom = 2; + UserJoinedRoomMessage userJoinedRoom = 1; + UserLeftRoomMessage userLeftRoom = 2; } } diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index f5915ddb..eedb1e7a 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -23,7 +23,7 @@ import { AdminPusherToBackMessage, ServerToAdminClientMessage, SendUserMessage, - BanUserMessage + BanUserMessage, UserJoinedRoomMessage, UserLeftRoomMessage } from "../Messages/generated/messages_pb"; import {PointInterface} from "../Model/Websocket/PointInterface"; import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils"; @@ -77,15 +77,28 @@ export class SocketManager implements ZoneEventListener { client.adminConnection = adminRoomStream; adminRoomStream.on('data', (message: ServerToAdminClientMessage) => { - if (message.hasUseruuidnamejoinedroom()) { - const userUuidName = message.getUseruuidnamejoinedroom(); + if (message.hasUserjoinedroom()) { + const userJoinedRoomMessage = message.getUserjoinedroom() as UserJoinedRoomMessage; if (!client.disconnecting) { - client.send('MemberJoin:'+userUuidName+';'+roomId); + client.send(JSON.stringify({ + type: 'MemberJoin', + data: { + uuid: userJoinedRoomMessage.getUuid(), + name: userJoinedRoomMessage.getName(), + ipAddress: userJoinedRoomMessage.getIpaddress(), + roomId: roomId, + } + })); } - } else if (message.hasUseruuidnameleftroom()) { - const userUuidName = message.getUseruuidnameleftroom(); + } else if (message.hasUserleftroom()) { + const userLeftRoomMessage = message.getUserleftroom() as UserLeftRoomMessage; if (!client.disconnecting) { - client.send('MemberLeave:'+userUuidName+';'+roomId); + client.send(JSON.stringify({ + type: 'MemberLeave', + data: { + uuid: userLeftRoomMessage.getUuid() + } + })); } } else { throw new Error('Unexpected admin message'); From 217b04dafa57b401dbbc686ce9bf7b646677fc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 15:31:07 +0100 Subject: [PATCH 11/17] Adding pusher CI --- .github/workflows/continuous_integration.yml | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 47b28d72..15abb31e 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -53,6 +53,49 @@ jobs: run: yarn test working-directory: "front" + continuous-integration-pusher: + name: "Continuous Integration Pusher" + + runs-on: "ubuntu-latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2.0.0" + + - name: "Setup NodeJS" + uses: actions/setup-node@v1 + with: + node-version: '12.x' + + - name: Install Protoc + uses: arduino/setup-protoc@v1 + with: + version: '3.x' + + - name: "Install dependencies" + run: yarn install + working-directory: "pusher" + + - name: "Install messages dependencies" + run: yarn install + working-directory: "messages" + + - name: "Build proto messages" + run: yarn run proto && yarn run copy-to-back + working-directory: "messages" + + - name: "Build" + run: yarn run tsc + working-directory: "pusher" + + - name: "Lint" + run: yarn run lint + working-directory: "pusher" + + - name: "Jasmine" + run: yarn test + working-directory: "pusher" + continuous-integration-back: name: "Continuous Integration Back" From 8fcc1534d8e2fcf51e99ae71521d282a59a4ab6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 15:31:19 +0100 Subject: [PATCH 12/17] Fixing let/const in Admin --- back/src/Model/Admin.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/back/src/Model/Admin.ts b/back/src/Model/Admin.ts index 9d9c85ce..a121d105 100644 --- a/back/src/Model/Admin.ts +++ b/back/src/Model/Admin.ts @@ -22,9 +22,9 @@ export class Admin { } public sendUserJoin(uuid: string, name: string, ip: string): void { - let serverToAdminClientMessage = new ServerToAdminClientMessage(); + const serverToAdminClientMessage = new ServerToAdminClientMessage(); - let userJoinedRoomMessage = new UserJoinedRoomMessage(); + const userJoinedRoomMessage = new UserJoinedRoomMessage(); userJoinedRoomMessage.setUuid(uuid); userJoinedRoomMessage.setName(name); userJoinedRoomMessage.setIpaddress(ip); @@ -35,9 +35,9 @@ export class Admin { } public sendUserLeft(uuid: string/*, name: string, ip: string*/): void { - let serverToAdminClientMessage = new ServerToAdminClientMessage(); + const serverToAdminClientMessage = new ServerToAdminClientMessage(); - let userLeftRoomMessage = new UserLeftRoomMessage(); + const userLeftRoomMessage = new UserLeftRoomMessage(); userLeftRoomMessage.setUuid(uuid); serverToAdminClientMessage.setUserleftroom(userLeftRoomMessage); From e0fcb38c4fdbf02f1c27c86be322b3cef99dca6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 15:34:22 +0100 Subject: [PATCH 13/17] Fixing CI pipeline --- .github/workflows/continuous_integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 15abb31e..8b40ff71 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -81,7 +81,7 @@ jobs: working-directory: "messages" - name: "Build proto messages" - run: yarn run proto && yarn run copy-to-back + run: yarn run proto && yarn run copy-to-pusher working-directory: "messages" - name: "Build" From 65d2c3dfb0f47a3c034dd44779d78e8fceac894e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 15:36:02 +0100 Subject: [PATCH 14/17] Disabling explicit any check on error handling --- front/src/Phaser/Reconnecting/ErrorScene.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts index d7fc2ab7..921eeb58 100644 --- a/front/src/Phaser/Reconnecting/ErrorScene.ts +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -65,6 +65,7 @@ export class ErrorScene extends Phaser.Scene { /** * Displays the error page, with an error message matching the "error" parameters passed in. */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any public static showError(error: any, scene: ScenePlugin): void { console.error(error); From 0d4808231adef618e2c8cfed08f4c7de71ec297f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 15:43:27 +0100 Subject: [PATCH 15/17] Linting code --- pusher/package.json | 4 ++-- pusher/src/Controller/BaseController.ts | 1 + pusher/src/Services/SocketManager.ts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pusher/package.json b/pusher/package.json index 09d6794a..7edf3d5d 100644 --- a/pusher/package.json +++ b/pusher/package.json @@ -10,8 +10,8 @@ "runprod": "node --max-old-space-size=4096 ./dist/server.js", "profile": "tsc && node --prof ./dist/server.js", "test": "ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json", - "lint": "node_modules/.bin/eslint src/ . --ext .ts", - "fix": "node_modules/.bin/eslint --fix src/ . --ext .ts" + "lint": "DEBUG= node_modules/.bin/eslint src/ . --ext .ts", + "fix": "DEBUG= node_modules/.bin/eslint --fix src/ . --ext .ts" }, "repository": { "type": "git", diff --git a/pusher/src/Controller/BaseController.ts b/pusher/src/Controller/BaseController.ts index 2096496d..673ffd3c 100644 --- a/pusher/src/Controller/BaseController.ts +++ b/pusher/src/Controller/BaseController.ts @@ -12,6 +12,7 @@ export class BaseController { /** * Turns any exception into a HTTP response (and logs the error) */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any protected errorToResponse(e: any, res: HttpResponse): void { console.error("An error happened", e); if (e.response) { diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index eedb1e7a..2f86ae19 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -544,7 +544,7 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } - public async emitSendUserMessage(userUuid: string, message: string, type: string): Promise { + public emitSendUserMessage(userUuid: string, message: string, type: string): void { const client = this.searchClientByUuid(userUuid); if(!client){ throw Error('client not found'); @@ -569,7 +569,7 @@ export class SocketManager implements ZoneEventListener { });*/ } - public async emitBan(userUuid: string, message: string, type: string): Promise { + public emitBan(userUuid: string, message: string, type: string): void { const client = this.searchClientByUuid(userUuid); if(!client){ throw Error('client not found'); From 5954ded19555ecbddc6913123641b6e62f73aab2 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Mon, 18 Jan 2021 16:25:44 +0100 Subject: [PATCH 16/17] Update link for private TCM map --- maps/Floor0/floor0.json | 2 +- maps/Floor1/floor1.json | 6 +++--- maps/Floor2/floor2.json | 4 ++-- maps/Lyon/lyon.json | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/maps/Floor0/floor0.json b/maps/Floor0/floor0.json index 6a88f78d..3bbd67cd 100644 --- a/maps/Floor0/floor0.json +++ b/maps/Floor0/floor0.json @@ -278,7 +278,7 @@ { "name":"exitUrl", "type":"string", - "value":"..\/Floor1\/floor1.json" + "value":"\/@\/tcm\/workadventure\/floor1" }], "type":"tilelayer", "visible":true, diff --git a/maps/Floor1/floor1.json b/maps/Floor1/floor1.json index 99f53093..6deb3bf5 100644 --- a/maps/Floor1/floor1.json +++ b/maps/Floor1/floor1.json @@ -85,7 +85,7 @@ { "name":"exitSceneUrl", "type":"string", - "value":"..\/Floor0\/floor0.json#down-the-stairs" + "value":"\/@\/tcm\/workadventure\/floor0#down-the-stairs" }], "type":"tilelayer", "visible":true, @@ -103,7 +103,7 @@ { "name":"exitSceneUrl", "type":"string", - "value":"..\/Floor2\/floor2.json#down-the-stairs" + "value":"\/@\/tcm\/workadventure\/floor2#down-the-stairs" }], "type":"tilelayer", "visible":true, @@ -121,7 +121,7 @@ { "name":"exitSceneUrl", "type":"string", - "value":"..\/Floor2\/floor2.json#down-the-stairs-secours" + "value":"\/@\/tcm\/workadventure\/floor2#down-the-stairs-secours" }], "type":"tilelayer", "visible":true, diff --git a/maps/Floor2/floor2.json b/maps/Floor2/floor2.json index a256e5f3..35454404 100644 --- a/maps/Floor2/floor2.json +++ b/maps/Floor2/floor2.json @@ -103,7 +103,7 @@ { "name":"exitSceneUrl", "type":"string", - "value":"..\/Floor1\/floor1.json#down-the-stairs" + "value":"\/@\/tcm\/workadventure\/floor1#down-the-stairs" }], "type":"tilelayer", "visible":true, @@ -139,7 +139,7 @@ { "name":"exitSceneUrl", "type":"string", - "value":"..\/Floor1\/floor1.json#down-the-stairs-secours" + "value":"\/@\/tcm\/workadventure\/floor1#down-the-stairs-secours" }], "type":"tilelayer", "visible":true, diff --git a/maps/Lyon/lyon.json b/maps/Lyon/lyon.json index 0ed62a9c..ddaf8ea8 100644 --- a/maps/Lyon/lyon.json +++ b/maps/Lyon/lyon.json @@ -37,7 +37,7 @@ { "name":"exitSceneUrl", "type":"string", - "value":"..\/Floor0\/floor0.json" + "value":"\/@\/tcm\/workadventure\/floor0" }], "type":"tilelayer", "visible":true, From 4df200c6c0d42026defde7451394dae01c5d7c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 18 Jan 2021 16:41:20 +0100 Subject: [PATCH 17/17] Switching ban by IP to be world specific --- pusher/src/Services/AdminApi.ts | 4 ++-- pusher/src/Services/JWTTokenManager.ts | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 75977482..48e8a1a4 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -116,12 +116,12 @@ class AdminApi { }); } - async verifyBanUser(organizationMemberToken: string, ipAddress: string, room: string): Promise { + async verifyBanUser(organizationMemberToken: string, ipAddress: string, organization: string, world: string): Promise { if (!ADMIN_API_URL) { return Promise.reject('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. - return Axios.get(ADMIN_API_URL + '/api/check-moderate-user/' + ipAddress + '/' + organizationMemberToken + '/room/' + room, + return Axios.get(ADMIN_API_URL + '/api/check-moderate-user/'+organization+'/'+world+'?ipAddress='+ipAddress+'&token='+organizationMemberToken, {headers: {"Authorization": `${ADMIN_API_TOKEN}`}} ).then((data) => { return data.data; diff --git a/pusher/src/Services/JWTTokenManager.ts b/pusher/src/Services/JWTTokenManager.ts index 6605ec4e..68d5488a 100644 --- a/pusher/src/Services/JWTTokenManager.ts +++ b/pusher/src/Services/JWTTokenManager.ts @@ -76,8 +76,17 @@ class JWTTokenManager { } private verifyBanUser(userUuid: string, ipAddress: string, room: string): Promise { - const world = room.split('/')[1]; //check by world - return adminApi.verifyBanUser(userUuid, ipAddress, world).then((data: AdminBannedData) => { + const parts = room.split('/'); + if (parts.length < 3 || parts[0] !== '@') { + return Promise.resolve({ + is_banned: false, + message: '' + }); + } + + const organization = parts[1]; + const world = parts[2]; + return adminApi.verifyBanUser(userUuid, ipAddress, organization, world).then((data: AdminBannedData) => { if (data && data.is_banned) { throw new Error('User was banned'); }