Create ban feature by admin console

This commit is contained in:
Gregoire Parant 2021-01-15 03:19:58 +01:00
parent 871ee6b192
commit b1f8522c05
10 changed files with 68 additions and 26 deletions

View file

@ -21,17 +21,15 @@ export class Admin {
) { ) {
} }
public sendUserJoin(uuid: string): void { public sendUserJoin(uuid: string, name: string, ip: string): void {
const serverToAdminClientMessage = new ServerToAdminClientMessage(); let serverToAdminClientMessage = new ServerToAdminClientMessage();
serverToAdminClientMessage.setUseruuidjoinedroom(uuid); serverToAdminClientMessage = serverToAdminClientMessage.setUseruuidnamejoinedroom(uuid+';'+name+';'+ip)
this.socket.write(serverToAdminClientMessage); this.socket.write(serverToAdminClientMessage);
} }
public sendUserLeft(uuid: string): void { public sendUserLeft(uuid: string, name: string, ip: string): void {
const serverToAdminClientMessage = new ServerToAdminClientMessage(); let serverToAdminClientMessage = new ServerToAdminClientMessage();
serverToAdminClientMessage.setUseruuidleftroom(uuid); serverToAdminClientMessage = serverToAdminClientMessage.setUseruuidnameleftroom(uuid+';'+name+';'+ip);
this.socket.write(serverToAdminClientMessage); this.socket.write(serverToAdminClientMessage);
} }
} }

View file

@ -102,7 +102,17 @@ export class GameRoom {
} }
const position = ProtobufUtils.toPointInterface(positionMessage); 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.nextUserId++;
this.users.set(user.id, user); this.users.set(user.id, user);
this.usersByUuid.set(user.uuid, user); this.usersByUuid.set(user.uuid, user);
@ -112,7 +122,7 @@ export class GameRoom {
// Notify admins // Notify admins
for (const admin of this.admins) { for (const admin of this.admins) {
admin.sendUserJoin(user.uuid); admin.sendUserJoin(user.uuid, user.name, user.IPAddress);
} }
return user; return user;
@ -135,7 +145,7 @@ export class GameRoom {
// Notify admins // Notify admins
for (const admin of this.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 // Let's send all connected users
for (const user of this.users.values()) { for (const user of this.users.values()) {
admin.sendUserJoin(user.uuid); admin.sendUserJoin(user.uuid, user.name, user.IPAddress);
} }
} }

View file

@ -16,6 +16,7 @@ export class User implements Movable {
public constructor( public constructor(
public id: number, public id: number,
public readonly uuid: string, public readonly uuid: string,
public readonly IPAddress: string,
private position: PointInterface, private position: PointInterface,
public silent: boolean, public silent: boolean,
private positionNotifier: PositionNotifier, private positionNotifier: PositionNotifier,

View file

@ -26,6 +26,7 @@ function createJoinRoomMessage(uuid: string, x: number, y: number): JoinRoomMess
positionMessage.setMoving(false); positionMessage.setMoving(false);
const joinRoomMessage = new JoinRoomMessage(); const joinRoomMessage = new JoinRoomMessage();
joinRoomMessage.setUseruuid('1'); joinRoomMessage.setUseruuid('1');
joinRoomMessage.setIpaddress('10.0.0.2');
joinRoomMessage.setName('foo'); joinRoomMessage.setName('foo');
joinRoomMessage.setRoomid('_/global/test.json'); joinRoomMessage.setRoomid('_/global/test.json');
joinRoomMessage.setPositionmessage(positionMessage); joinRoomMessage.setPositionmessage(positionMessage);

View file

@ -220,6 +220,7 @@ message JoinRoomMessage {
string userUuid = 4; string userUuid = 4;
string roomId = 5; string roomId = 5;
repeated string tag = 6; repeated string tag = 6;
string IPAddress = 7;
} }
message UserJoinedZoneMessage { message UserJoinedZoneMessage {
@ -308,8 +309,8 @@ message ServerToAdminClientMessage {
message ServerToAdminClientMessage { message ServerToAdminClientMessage {
oneof message { oneof message {
string userUuidJoinedRoom = 1; string userUuidNameJoinedRoom = 1;
string userUuidLeftRoom = 2; string userUuidNameLeftRoom = 2;
} }
} }

View file

@ -148,6 +148,7 @@ export class IoSocketController {
const websocketKey = req.getHeader('sec-websocket-key'); const websocketKey = req.getHeader('sec-websocket-key');
const websocketProtocol = req.getHeader('sec-websocket-protocol'); const websocketProtocol = req.getHeader('sec-websocket-protocol');
const websocketExtensions = req.getHeader('sec-websocket-extensions'); const websocketExtensions = req.getHeader('sec-websocket-extensions');
const IPAddress = req.getHeader('x-forwarded-for');
const roomId = query.roomId; const roomId = query.roomId;
if (typeof roomId !== 'string') { if (typeof roomId !== 'string') {
@ -177,7 +178,8 @@ export class IoSocketController {
} }
const userUuid = await jwtTokenManager.getUserUuidFromToken(token); const userUuid = await jwtTokenManager.getUserUuidFromToken(token);
//TODO send ban message
await jwtTokenManager.verifyBanUser(userUuid, IPAddress, roomId);
let memberTags: string[] = []; let memberTags: string[] = [];
let memberTextures: CharacterTexture[] = []; let memberTextures: CharacterTexture[] = [];
const room = await socketManager.getOrCreateRoom(roomId); const room = await socketManager.getOrCreateRoom(roomId);
@ -217,6 +219,7 @@ export class IoSocketController {
url, url,
token, token,
userUuid, userUuid,
IPAddress,
roomId, roomId,
name, name,
characterLayers: characterLayerObjs, characterLayers: characterLayerObjs,
@ -336,6 +339,7 @@ export class IoSocketController {
client.userId = this.nextUserId; client.userId = this.nextUserId;
this.nextUserId++; this.nextUserId++;
client.userUuid = ws.userUuid; client.userUuid = ws.userUuid;
client.IPAddress = ws.IPAddress;
client.token = ws.token; client.token = ws.token;
client.batchedMessages = new BatchMessage(); client.batchedMessages = new BatchMessage();
client.batchTimeout = null; client.batchTimeout = null;

View file

@ -24,6 +24,7 @@ export interface ExSocketInterface extends WebSocket, Identificable {
roomId: string; roomId: string;
//userId: number; // A temporary (autoincremented) identifier for this user //userId: number; // A temporary (autoincremented) identifier for this user
userUuid: string; // A unique identifier for this user userUuid: string; // A unique identifier for this user
IPAddress: string; // IP address
name: string; name: string;
characterLayers: CharacterLayer[]; characterLayers: CharacterLayer[];
position: PointInterface; position: PointInterface;

View file

@ -14,6 +14,11 @@ export interface AdminApiData {
textures: CharacterTexture[] textures: CharacterTexture[]
} }
export interface AdminBannedData {
is_banned: boolean,
message: string
}
export interface CharacterTexture { export interface CharacterTexture {
id: number, id: number,
level: number, level: number,
@ -110,6 +115,18 @@ class AdminApi {
headers: {"Authorization": `${ADMIN_API_TOKEN}`} headers: {"Authorization": `${ADMIN_API_TOKEN}`}
}); });
} }
async verifyBanUser(organizationMemberToken: string, ipAddress: string, room: string): Promise<AdminBannedData> {
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(); export const adminApi = new AdminApi();

View file

@ -2,7 +2,7 @@ import {ADMIN_API_URL, ALLOW_ARTILLERY, SECRET_KEY} from "../Enum/EnvironmentVar
import {uuid} from "uuidv4"; import {uuid} from "uuidv4";
import Jwt from "jsonwebtoken"; import Jwt from "jsonwebtoken";
import {TokenInterface} from "../Controller/AuthenticateController"; import {TokenInterface} from "../Controller/AuthenticateController";
import {adminApi, AdminApiData} from "../Services/AdminApi"; import {adminApi, AdminBannedData} from "../Services/AdminApi";
class JWTTokenManager { class JWTTokenManager {
@ -54,7 +54,7 @@ class JWTTokenManager {
resolve(tokenInterface.userUuid); resolve(tokenInterface.userUuid);
}).catch((err) => { }).catch((err) => {
//anonymous user //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); resolve(tokenInterface.userUuid);
return; return;
} }
@ -67,6 +67,17 @@ class JWTTokenManager {
}); });
} }
public async verifyBanUser(userUuid: string, ipAddress: string, room: string): Promise<unknown> {
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 { private isValidToken(token: object): token is TokenInterface {
return !(typeof((token as TokenInterface).userUuid) !== 'string'); return !(typeof((token as TokenInterface).userUuid) !== 'string');
} }

View file

@ -79,23 +79,20 @@ export class SocketManager implements ZoneEventListener {
} }
async handleAdminRoom(client: ExAdminSocketInterface, roomId: string): Promise<void> { async handleAdminRoom(client: ExAdminSocketInterface, roomId: string): Promise<void> {
console.log('Calling adminRoom')
const apiClient = await apiClientRepository.getClient(roomId); const apiClient = await apiClientRepository.getClient(roomId);
const adminRoomStream = apiClient.adminRoom(); const adminRoomStream = apiClient.adminRoom();
client.adminConnection = adminRoomStream; client.adminConnection = adminRoomStream;
adminRoomStream.on('data', (message: ServerToAdminClientMessage) => { adminRoomStream.on('data', (message: ServerToAdminClientMessage) => {
if (message.hasUseruuidjoinedroom()) { if (message.hasUseruuidnamejoinedroom()) {
const userUuid = message.getUseruuidjoinedroom(); const userUuidName = message.getUseruuidnamejoinedroom();
if (!client.disconnecting) { if (!client.disconnecting) {
client.send('MemberJoin:'+userUuid+';'+roomId); client.send('MemberJoin:'+userUuidName+';'+roomId);
} }
} else if (message.hasUseruuidleftroom()) { } else if (message.hasUseruuidnameleftroom()) {
const userUuid = message.getUseruuidleftroom(); const userUuidName = message.getUseruuidnameleftroom();
if (!client.disconnecting) { if (!client.disconnecting) {
client.send('MemberLeave:'+userUuid+';'+roomId); client.send('MemberLeave:'+userUuidName+';'+roomId);
} }
} else { } else {
throw new Error('Unexpected admin message'); throw new Error('Unexpected admin message');
@ -151,6 +148,7 @@ export class SocketManager implements ZoneEventListener {
const joinRoomMessage = new JoinRoomMessage(); const joinRoomMessage = new JoinRoomMessage();
joinRoomMessage.setUseruuid(client.userUuid); joinRoomMessage.setUseruuid(client.userUuid);
joinRoomMessage.setIpaddress(client.IPAddress);
joinRoomMessage.setRoomid(client.roomId); joinRoomMessage.setRoomid(client.roomId);
joinRoomMessage.setName(client.name); joinRoomMessage.setName(client.name);
joinRoomMessage.setPositionmessage(ProtobufUtils.toPositionMessage(client.position)); joinRoomMessage.setPositionmessage(ProtobufUtils.toPositionMessage(client.position));