From d2ee52ce43f80d6abb0e02ef56313e7041dacaae Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Fri, 15 Jan 2021 03:14:15 +0100 Subject: [PATCH] Update ban feature --- 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));