From 65cefb35845ebc340b73f49806df468ae3058b05 Mon Sep 17 00:00:00 2001 From: jonny Date: Thu, 1 Jul 2021 15:50:40 +0200 Subject: [PATCH 1/5] fixed invalid unauathorized handler --- back/src/Controller/DebugController.ts | 2 +- pusher/src/Controller/DebugController.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/Controller/DebugController.ts b/back/src/Controller/DebugController.ts index b7f037fd..88287753 100644 --- a/back/src/Controller/DebugController.ts +++ b/back/src/Controller/DebugController.ts @@ -15,7 +15,7 @@ export class DebugController { const query = parse(req.getQuery()); if (query.token !== ADMIN_API_TOKEN) { - return res.status(401).send("Invalid token sent!"); + return res.writeStatus("401 Unauthorized").end("Invalid token sent!"); } return res diff --git a/pusher/src/Controller/DebugController.ts b/pusher/src/Controller/DebugController.ts index 0b0d188b..e9e3540d 100644 --- a/pusher/src/Controller/DebugController.ts +++ b/pusher/src/Controller/DebugController.ts @@ -16,7 +16,7 @@ export class DebugController { const query = parse(req.getQuery()); if (query.token !== ADMIN_API_TOKEN) { - return res.status(401).send("Invalid token sent!"); + return res.writeStatus("401 Unauthorized").end("Invalid token sent!"); } return res From 46e6917df6a26969d3a7e7a4ec7862bee61aa39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Tue, 6 Jul 2021 17:13:08 +0200 Subject: [PATCH 2/5] Adding a playersStore The playerStore can be useful to get the details of a given player from its ID. --- back/src/Services/SocketManager.ts | 2 - front/src/Connexion/RoomConnection.ts | 1 - front/src/Phaser/Game/AddPlayerInterface.ts | 9 +---- front/src/Phaser/Game/GameScene.ts | 3 ++ front/src/Phaser/Game/PlayerInterface.ts | 9 +++++ front/src/Stores/PlayersStore.ts | 43 +++++++++++++++++++++ front/src/WebRtc/SimplePeer.ts | 16 ++------ messages/protos/messages.proto | 3 +- 8 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 front/src/Phaser/Game/PlayerInterface.ts create mode 100644 front/src/Stores/PlayersStore.ts diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index e61763cd..fd812b44 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -425,7 +425,6 @@ export class SocketManager { // Let's send 2 messages: one to the user joining the group and one to the other user const webrtcStartMessage1 = new WebRtcStartMessage(); webrtcStartMessage1.setUserid(otherUser.id); - webrtcStartMessage1.setName(otherUser.name); webrtcStartMessage1.setInitiator(true); if (TURN_STATIC_AUTH_SECRET !== "") { const { username, password } = this.getTURNCredentials("" + otherUser.id, TURN_STATIC_AUTH_SECRET); @@ -443,7 +442,6 @@ export class SocketManager { const webrtcStartMessage2 = new WebRtcStartMessage(); webrtcStartMessage2.setUserid(user.id); - webrtcStartMessage2.setName(user.name); webrtcStartMessage2.setInitiator(false); if (TURN_STATIC_AUTH_SECRET !== "") { const { username, password } = this.getTURNCredentials("" + user.id, TURN_STATIC_AUTH_SECRET); diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 1b080a55..4f2e9ef4 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -466,7 +466,6 @@ export class RoomConnection implements RoomConnection { this.onMessage(EventMessage.WEBRTC_START, (message: WebRtcStartMessage) => { callback({ userId: message.getUserid(), - name: message.getName(), initiator: message.getInitiator(), webRtcUser: message.getWebrtcusername() ?? undefined, webRtcPassword: message.getWebrtcpassword() ?? undefined, diff --git a/front/src/Phaser/Game/AddPlayerInterface.ts b/front/src/Phaser/Game/AddPlayerInterface.ts index 1a5176f0..d2f12013 100644 --- a/front/src/Phaser/Game/AddPlayerInterface.ts +++ b/front/src/Phaser/Game/AddPlayerInterface.ts @@ -1,11 +1,6 @@ import type {PointInterface} from "../../Connexion/ConnexionModels"; -import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures"; +import type {PlayerInterface} from "./PlayerInterface"; -export interface AddPlayerInterface { - userId: number; - name: string; - characterLayers: BodyResourceDescriptionInterface[]; +export interface AddPlayerInterface extends PlayerInterface { position: PointInterface; - visitCardUrl: string|null; - companion: string|null; } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d767f0f4..ce9ce5e4 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -91,6 +91,7 @@ import { soundManager } from "./SoundManager"; import { peerStore, screenSharingPeerStore } from "../../Stores/PeerStore"; import { videoFocusStore } from "../../Stores/VideoFocusStore"; import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore"; +import {playersStore} from "../../Stores/PlayersStore"; export interface GameSceneInitInterface { initPosition: PointInterface | null; @@ -597,6 +598,8 @@ export class GameScene extends DirtyScene { .then((onConnect: OnConnectInterface) => { this.connection = onConnect.connection; + playersStore.connectToRoomConnection(this.connection); + this.connection.onUserJoins((message: MessageUserJoined) => { const userMessage: AddPlayerInterface = { userId: message.userId, diff --git a/front/src/Phaser/Game/PlayerInterface.ts b/front/src/Phaser/Game/PlayerInterface.ts new file mode 100644 index 00000000..ab881267 --- /dev/null +++ b/front/src/Phaser/Game/PlayerInterface.ts @@ -0,0 +1,9 @@ +import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures"; + +export interface PlayerInterface { + userId: number; + name: string; + characterLayers: BodyResourceDescriptionInterface[]; + visitCardUrl: string|null; + companion: string|null; +} diff --git a/front/src/Stores/PlayersStore.ts b/front/src/Stores/PlayersStore.ts new file mode 100644 index 00000000..ef19efce --- /dev/null +++ b/front/src/Stores/PlayersStore.ts @@ -0,0 +1,43 @@ +import { writable } from "svelte/store"; +import type {PlayerInterface} from "../Phaser/Game/PlayerInterface"; +import type {RoomConnection} from "../Connexion/RoomConnection"; + +/** + * A store that contains the list of players currently known. + */ +function createPlayersStore() { + let players = new Map(); + + const { subscribe, set, update } = writable(players); + + return { + subscribe, + connectToRoomConnection: (roomConnection: RoomConnection) => { + players = new Map(); + set(players); + roomConnection.onUserJoins((message) => { + update((users) => { + users.set(message.userId, { + userId: message.userId, + name: message.name, + characterLayers: message.characterLayers, + visitCardUrl: message.visitCardUrl, + companion: message.companion, + }); + return users; + }); + }); + roomConnection.onUserLeft((userId) => { + update((users) => { + users.delete(userId); + return users; + }); + }); + }, + getPlayerById(userId: number): PlayerInterface|undefined { + return players.get(userId); + } + }; +} + +export const playersStore = createPlayersStore(); diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index affcacd7..0d3c4745 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -11,10 +11,10 @@ import { get } from "svelte/store"; import { localStreamStore, LocalStreamStoreValue, obtainedMediaConstraintStore } from "../Stores/MediaStore"; import { screenSharingLocalStreamStore } from "../Stores/ScreenSharingStore"; import { discussionManager } from "./DiscussionManager"; +import {playersStore} from "../Stores/PlayersStore"; export interface UserSimplePeerInterface { userId: number; - name?: string; initiator?: boolean; webRtcUser?: string | undefined; webRtcPassword?: string | undefined; @@ -153,10 +153,7 @@ export class SimplePeer { } } - let name = user.name; - if (!name) { - name = this.getName(user.userId); - } + const name = this.getName(user.userId); discussionManager.removeParticipant(user.userId); @@ -191,7 +188,7 @@ export class SimplePeer { //Create a notification for first user in circle discussion if (this.PeerConnectionArray.size === 0) { - mediaManager.createNotification(user.name ?? ""); + mediaManager.createNotification(name); } this.PeerConnectionArray.set(user.userId, peer); @@ -202,12 +199,7 @@ export class SimplePeer { } private getName(userId: number): string { - const userSearch = this.Users.find((userSearch: UserSimplePeerInterface) => userSearch.userId === userId); - if (userSearch) { - return userSearch.name || ""; - } else { - return ""; - } + return playersStore.getPlayerById(userId)?.name || ''; } /** diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 52d58d6d..27d7cb10 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -183,7 +183,6 @@ message RoomJoinedMessage { message WebRtcStartMessage { int32 userId = 1; - string name = 2; bool initiator = 3; string webrtcUserName = 4; string webrtcPassword = 5; @@ -257,7 +256,7 @@ message ServerToClientMessage { AdminRoomMessage adminRoomMessage = 14; WorldFullWarningMessage worldFullWarningMessage = 15; WorldFullMessage worldFullMessage = 16; - RefreshRoomMessage refreshRoomMessage = 17; + RefreshRoomMessage refreshRoomMessage = 17; WorldConnexionMessage worldConnexionMessage = 18; EmoteEventMessage emoteEventMessage = 19; } From 34cb0ebf39e2d21acc5ed9ddb6113259db85e7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Wed, 7 Jul 2021 11:24:51 +0200 Subject: [PATCH 3/5] Users blocking now rely on UUID rather than ID This way, if a user A blocks another user B, if user B refreshes the browser or leaves and re-enters the room, user B will still be blocked. As a side effect, this allows us to completely remove the "sockets" property in the SocketManager on the Pusher. --- CHANGELOG.md | 1 + back/src/Services/SocketManager.ts | 2 + front/src/Connexion/ConnexionModels.ts | 68 +++++++++++---------- front/src/Connexion/RoomConnection.ts | 5 +- front/src/Phaser/Game/GameScene.ts | 7 ++- front/src/Phaser/Game/PlayerInterface.ts | 7 ++- front/src/Phaser/Menu/MenuScene.ts | 7 ++- front/src/Phaser/Menu/ReportMenu.ts | 78 ++++++++++++------------ front/src/Stores/PlayersStore.ts | 9 +-- front/src/WebRtc/BlackListManager.ts | 37 +++++------ front/src/WebRtc/SimplePeer.ts | 10 +-- front/src/WebRtc/VideoPeer.ts | 15 +++-- messages/protos/messages.proto | 4 +- pusher/src/Model/Zone.ts | 3 + pusher/src/Services/SocketManager.ts | 31 +--------- 15 files changed, 143 insertions(+), 141 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa3dd293..a83e8213 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Use `WA.room.getCurrentRoom(): Promise` to get the ID, JSON map file, url of the map of the current room and the layer where the current player started - Use `WA.ui.registerMenuCommand(): void` to add a custom menu - Use `WA.room.setTiles(): void` to change an array of tiles +- Users blocking now relies on UUID rather than ID. A blocked user that leaves a room and comes back will stay blocked. ## Version 1.4.3 - 1.4.4 - 1.4.5 diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index fd812b44..8d04e713 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -308,6 +308,7 @@ export class SocketManager { throw new Error("clientUser.userId is not an integer " + thing.id); } userJoinedZoneMessage.setUserid(thing.id); + userJoinedZoneMessage.setUseruuid(thing.uuid); userJoinedZoneMessage.setName(thing.name); userJoinedZoneMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers)); userJoinedZoneMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition())); @@ -612,6 +613,7 @@ export class SocketManager { if (thing instanceof User) { const userJoinedMessage = new UserJoinedZoneMessage(); userJoinedMessage.setUserid(thing.id); + userJoinedMessage.setUseruuid(thing.uuid); userJoinedMessage.setName(thing.name); userJoinedMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers)); userJoinedMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition())); diff --git a/front/src/Connexion/ConnexionModels.ts b/front/src/Connexion/ConnexionModels.ts index b5a66296..189aea7c 100644 --- a/front/src/Connexion/ConnexionModels.ts +++ b/front/src/Connexion/ConnexionModels.ts @@ -1,8 +1,8 @@ -import type {SignalData} from "simple-peer"; -import type {RoomConnection} from "./RoomConnection"; -import type {BodyResourceDescriptionInterface} from "../Phaser/Entity/PlayerTextures"; +import type { SignalData } from "simple-peer"; +import type { RoomConnection } from "./RoomConnection"; +import type { BodyResourceDescriptionInterface } from "../Phaser/Entity/PlayerTextures"; -export enum EventMessage{ +export enum EventMessage { CONNECT = "connect", WEBRTC_SIGNAL = "webrtc-signal", WEBRTC_SCREEN_SHARING_SIGNAL = "webrtc-screen-sharing-signal", @@ -17,7 +17,7 @@ export enum EventMessage{ GROUP_CREATE_UPDATE = "group-create-update", GROUP_DELETE = "group-delete", SET_PLAYER_DETAILS = "set-player-details", // Send the name and character to the server (on connect), receive back the id. - ITEM_EVENT = 'item-event', + ITEM_EVENT = "item-event", CONNECT_ERROR = "connect_error", CONNECTING_ERROR = "connecting_error", @@ -36,7 +36,7 @@ export enum EventMessage{ export interface PointInterface { x: number; y: number; - direction : string; + direction: string; moving: boolean; } @@ -45,8 +45,9 @@ export interface MessageUserPositionInterface { name: string; characterLayers: BodyResourceDescriptionInterface[]; position: PointInterface; - visitCardUrl: string|null; - companion: string|null; + visitCardUrl: string | null; + companion: string | null; + userUuid: string; } export interface MessageUserMovedInterface { @@ -60,58 +61,59 @@ export interface MessageUserJoined { characterLayers: BodyResourceDescriptionInterface[]; position: PointInterface; visitCardUrl: string | null; - companion: string|null; + companion: string | null; + userUuid: string; } export interface PositionInterface { - x: number, - y: number + x: number; + y: number; } export interface GroupCreatedUpdatedMessageInterface { - position: PositionInterface, - groupId: number, - groupSize: number + position: PositionInterface; + groupId: number; + groupSize: number; } export interface WebRtcDisconnectMessageInterface { - userId: number + userId: number; } export interface WebRtcSignalReceivedMessageInterface { - userId: number, - signal: SignalData, - webRtcUser: string | undefined, - webRtcPassword: string | undefined + userId: number; + signal: SignalData; + webRtcUser: string | undefined; + webRtcPassword: string | undefined; } export interface ViewportInterface { - left: number, - top: number, - right: number, - bottom: number, + left: number; + top: number; + right: number; + bottom: number; } export interface ItemEventMessageInterface { - itemId: number, - event: string, - state: unknown, - parameters: unknown + itemId: number; + event: string; + state: unknown; + parameters: unknown; } export interface RoomJoinedMessageInterface { //users: MessageUserPositionInterface[], //groups: GroupCreatedUpdatedMessageInterface[], - items: { [itemId: number] : unknown } + items: { [itemId: number]: unknown }; } export interface PlayGlobalMessageInterface { - id: string - type: string - message: string + id: string; + type: string; + message: string; } export interface OnConnectInterface { - connection: RoomConnection, - room: RoomJoinedMessageInterface + connection: RoomConnection; + room: RoomJoinedMessageInterface; } diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 4f2e9ef4..189eabba 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -365,6 +365,7 @@ export class RoomConnection implements RoomConnection { visitCardUrl: message.getVisitcardurl(), position: ProtobufClientUtils.toPointInterface(position), companion: companion ? companion.getName() : null, + userUuid: message.getUseruuid(), }; } @@ -591,9 +592,9 @@ export class RoomConnection implements RoomConnection { this.socket.send(clientToServerMessage.serializeBinary().buffer); } - public emitReportPlayerMessage(reportedUserId: number, reportComment: string): void { + public emitReportPlayerMessage(reportedUserUuid: string, reportComment: string): void { const reportPlayerMessage = new ReportPlayerMessage(); - reportPlayerMessage.setReporteduserid(reportedUserId); + reportPlayerMessage.setReporteduseruuid(reportedUserUuid); reportPlayerMessage.setReportcomment(reportComment); const clientToServerMessage = new ClientToServerMessage(); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index ce9ce5e4..d6df242f 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -91,7 +91,7 @@ import { soundManager } from "./SoundManager"; import { peerStore, screenSharingPeerStore } from "../../Stores/PeerStore"; import { videoFocusStore } from "../../Stores/VideoFocusStore"; import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore"; -import {playersStore} from "../../Stores/PlayersStore"; +import { playersStore } from "../../Stores/PlayersStore"; export interface GameSceneInitInterface { initPosition: PointInterface | null; @@ -608,6 +608,7 @@ export class GameScene extends DirtyScene { position: message.position, visitCardUrl: message.visitCardUrl, companion: message.companion, + userUuid: message.userUuid, }; this.addPlayer(userMessage); }); @@ -1047,7 +1048,7 @@ ${escapedMessage} }) ); - iframeListener.registerAnswerer('getState', () => { + iframeListener.registerAnswerer("getState", () => { return { mapUrl: this.MapUrlFile, startLayerName: this.startPositionCalculator.startLayerName, @@ -1150,7 +1151,7 @@ ${escapedMessage} this.emoteManager.destroy(); this.peerStoreUnsubscribe(); this.biggestAvailableAreaStoreUnsubscribe(); - iframeListener.unregisterAnswerer('getState'); + iframeListener.unregisterAnswerer("getState"); mediaManager.hideGameOverlay(); diff --git a/front/src/Phaser/Game/PlayerInterface.ts b/front/src/Phaser/Game/PlayerInterface.ts index ab881267..5a81c89a 100644 --- a/front/src/Phaser/Game/PlayerInterface.ts +++ b/front/src/Phaser/Game/PlayerInterface.ts @@ -1,9 +1,10 @@ -import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures"; +import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures"; export interface PlayerInterface { userId: number; name: string; characterLayers: BodyResourceDescriptionInterface[]; - visitCardUrl: string|null; - companion: string|null; + visitCardUrl: string | null; + companion: string | null; + userUuid: string; } diff --git a/front/src/Phaser/Menu/MenuScene.ts b/front/src/Phaser/Menu/MenuScene.ts index d0d6f982..da59cecb 100644 --- a/front/src/Phaser/Menu/MenuScene.ts +++ b/front/src/Phaser/Menu/MenuScene.ts @@ -18,6 +18,7 @@ import { registerMenuCommandStream } from "../../Api/Events/ui/MenuItemRegisterE import { sendMenuClickedEvent } from "../../Api/iframe/Ui/MenuItem"; import { consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore"; import { get } from "svelte/store"; +import { playersStore } from "../../Stores/PlayersStore"; export const MenuSceneName = "MenuScene"; const gameMenuKey = "gameMenu"; @@ -120,7 +121,11 @@ export class MenuScene extends Phaser.Scene { showReportScreenStore.subscribe((user) => { if (user !== null) { this.closeAll(); - this.gameReportElement.open(user.userId, user.userName); + const uuid = playersStore.getPlayerById(user.userId)?.userUuid; + if (uuid === undefined) { + throw new Error("Could not find UUID for user with ID " + user.userId); + } + this.gameReportElement.open(uuid, user.userName); } }); diff --git a/front/src/Phaser/Menu/ReportMenu.ts b/front/src/Phaser/Menu/ReportMenu.ts index e8b20531..effb92b2 100644 --- a/front/src/Phaser/Menu/ReportMenu.ts +++ b/front/src/Phaser/Menu/ReportMenu.ts @@ -1,15 +1,16 @@ -import {MenuScene} from "./MenuScene"; -import {gameManager} from "../Game/GameManager"; -import {blackListManager} from "../../WebRtc/BlackListManager"; +import { MenuScene } from "./MenuScene"; +import { gameManager } from "../Game/GameManager"; +import { blackListManager } from "../../WebRtc/BlackListManager"; +import { playersStore } from "../../Stores/PlayersStore"; -export const gameReportKey = 'gameReport'; -export const gameReportRessource = 'resources/html/gameReport.html'; +export const gameReportKey = "gameReport"; +export const gameReportRessource = "resources/html/gameReport.html"; export class ReportMenu extends Phaser.GameObjects.DOMElement { private opened: boolean = false; - private userId!: number; - private userName!: string|undefined; + private userUuid!: string; + private userName!: string | undefined; private anonymous: boolean; constructor(scene: Phaser.Scene, anonymous: boolean) { @@ -18,46 +19,46 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement { this.createFromCache(gameReportKey); if (this.anonymous) { - const divToHide = this.getChildByID('reportSection') as HTMLElement; + const divToHide = this.getChildByID("reportSection") as HTMLElement; divToHide.hidden = true; - const textToHide = this.getChildByID('askActionP') as HTMLElement; + const textToHide = this.getChildByID("askActionP") as HTMLElement; textToHide.hidden = true; } scene.add.existing(this); MenuScene.revealMenusAfterInit(this, gameReportKey); - this.addListener('click'); - this.on('click', (event:MouseEvent) => { + this.addListener("click"); + this.on("click", (event: MouseEvent) => { event.preventDefault(); - if ((event?.target as HTMLInputElement).id === 'gameReportFormSubmit') { + if ((event?.target as HTMLInputElement).id === "gameReportFormSubmit") { this.submitReport(); - } else if((event?.target as HTMLInputElement).id === 'gameReportFormCancel') { + } else if ((event?.target as HTMLInputElement).id === "gameReportFormCancel") { this.close(); - } else if((event?.target as HTMLInputElement).id === 'toggleBlockButton') { + } else if ((event?.target as HTMLInputElement).id === "toggleBlockButton") { this.toggleBlock(); } }); } - public open(userId: number, userName: string|undefined): void { + public open(userUuid: string, userName: string | undefined): void { if (this.opened) { this.close(); return; } - this.userId = userId; + this.userUuid = userUuid; this.userName = userName; - const mainEl = this.getChildByID('gameReport') as HTMLElement; + const mainEl = this.getChildByID("gameReport") as HTMLElement; this.x = this.getCenteredX(mainEl); this.y = this.getHiddenY(mainEl); - const gameTitleReport = this.getChildByID('nameReported') as HTMLElement; - gameTitleReport.innerText = userName || ''; + const gameTitleReport = this.getChildByID("nameReported") as HTMLElement; + gameTitleReport.innerText = userName || ""; - const blockButton = this.getChildByID('toggleBlockButton') as HTMLElement; - blockButton.innerText = blackListManager.isBlackListed(this.userId) ? 'Unblock this user' : 'Block this user'; + const blockButton = this.getChildByID("toggleBlockButton") as HTMLElement; + blockButton.innerText = blackListManager.isBlackListed(this.userUuid) ? "Unblock this user" : "Block this user"; this.opened = true; @@ -67,19 +68,19 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement { targets: this, y: this.getCenteredY(mainEl), duration: 1000, - ease: 'Power3' + ease: "Power3", }); } public close(): void { gameManager.getCurrentGameScene(this.scene).userInputManager.restoreControls(); this.opened = false; - const mainEl = this.getChildByID('gameReport') as HTMLElement; + const mainEl = this.getChildByID("gameReport") as HTMLElement; this.scene.tweens.add({ targets: this, y: this.getHiddenY(mainEl), duration: 1000, - ease: 'Power3' + ease: "Power3", }); } @@ -88,31 +89,32 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement { return window.innerWidth / 4 - mainEl.clientWidth / 2; } private getHiddenY(mainEl: HTMLElement): number { - return - mainEl.clientHeight - 50; + return -mainEl.clientHeight - 50; } private getCenteredY(mainEl: HTMLElement): number { return window.innerHeight / 4 - mainEl.clientHeight / 2; } private toggleBlock(): void { - !blackListManager.isBlackListed(this.userId) ? blackListManager.blackList(this.userId) : blackListManager.cancelBlackList(this.userId); + !blackListManager.isBlackListed(this.userUuid) + ? blackListManager.blackList(this.userUuid) + : blackListManager.cancelBlackList(this.userUuid); this.close(); } - private submitReport(): void{ - const gamePError = this.getChildByID('gameReportErr') as HTMLParagraphElement; - gamePError.innerText = ''; - gamePError.style.display = 'none'; - const gameTextArea = this.getChildByID('gameReportInput') as HTMLInputElement; - if(!gameTextArea || !gameTextArea.value){ - gamePError.innerText = 'Report message cannot to be empty.'; - gamePError.style.display = 'block'; + private submitReport(): void { + const gamePError = this.getChildByID("gameReportErr") as HTMLParagraphElement; + gamePError.innerText = ""; + gamePError.style.display = "none"; + const gameTextArea = this.getChildByID("gameReportInput") as HTMLInputElement; + if (!gameTextArea || !gameTextArea.value) { + gamePError.innerText = "Report message cannot to be empty."; + gamePError.style.display = "block"; return; } - gameManager.getCurrentGameScene(this.scene).connection?.emitReportPlayerMessage( - this.userId, - gameTextArea.value - ); + gameManager + .getCurrentGameScene(this.scene) + .connection?.emitReportPlayerMessage(this.userUuid, gameTextArea.value); this.close(); } } diff --git a/front/src/Stores/PlayersStore.ts b/front/src/Stores/PlayersStore.ts index ef19efce..6c21de7a 100644 --- a/front/src/Stores/PlayersStore.ts +++ b/front/src/Stores/PlayersStore.ts @@ -1,6 +1,6 @@ import { writable } from "svelte/store"; -import type {PlayerInterface} from "../Phaser/Game/PlayerInterface"; -import type {RoomConnection} from "../Connexion/RoomConnection"; +import type { PlayerInterface } from "../Phaser/Game/PlayerInterface"; +import type { RoomConnection } from "../Connexion/RoomConnection"; /** * A store that contains the list of players currently known. @@ -23,6 +23,7 @@ function createPlayersStore() { characterLayers: message.characterLayers, visitCardUrl: message.visitCardUrl, companion: message.companion, + userUuid: message.userUuid, }); return users; }); @@ -34,9 +35,9 @@ function createPlayersStore() { }); }); }, - getPlayerById(userId: number): PlayerInterface|undefined { + getPlayerById(userId: number): PlayerInterface | undefined { return players.get(userId); - } + }, }; } diff --git a/front/src/WebRtc/BlackListManager.ts b/front/src/WebRtc/BlackListManager.ts index 65efef3a..d2e7c390 100644 --- a/front/src/WebRtc/BlackListManager.ts +++ b/front/src/WebRtc/BlackListManager.ts @@ -1,24 +1,27 @@ -import {Subject} from 'rxjs'; +import { Subject } from "rxjs"; class BlackListManager { - private list: number[] = []; - public onBlockStream: Subject = new Subject(); - public onUnBlockStream: Subject = new Subject(); - - isBlackListed(userId: number): boolean { - return this.list.find((data) => data === userId) !== undefined; - } - - blackList(userId: number): void { - if (this.isBlackListed(userId)) return; - this.list.push(userId); - this.onBlockStream.next(userId); + private list: string[] = []; + public onBlockStream: Subject = new Subject(); + public onUnBlockStream: Subject = new Subject(); + + isBlackListed(userUuid: string): boolean { + return this.list.find((data) => data === userUuid) !== undefined; } - cancelBlackList(userId: number): void { - this.list.splice(this.list.findIndex(data => data === userId), 1); - this.onUnBlockStream.next(userId); + blackList(userUuid: string): void { + if (this.isBlackListed(userUuid)) return; + this.list.push(userUuid); + this.onBlockStream.next(userUuid); + } + + cancelBlackList(userUuid: string): void { + this.list.splice( + this.list.findIndex((data) => data === userUuid), + 1 + ); + this.onUnBlockStream.next(userUuid); } } -export const blackListManager = new BlackListManager(); \ No newline at end of file +export const blackListManager = new BlackListManager(); diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 0d3c4745..5045a5a3 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -11,7 +11,7 @@ import { get } from "svelte/store"; import { localStreamStore, LocalStreamStoreValue, obtainedMediaConstraintStore } from "../Stores/MediaStore"; import { screenSharingLocalStreamStore } from "../Stores/ScreenSharingStore"; import { discussionManager } from "./DiscussionManager"; -import {playersStore} from "../Stores/PlayersStore"; +import { playersStore } from "../Stores/PlayersStore"; export interface UserSimplePeerInterface { userId: number; @@ -199,7 +199,7 @@ export class SimplePeer { } private getName(userId: number): string { - return playersStore.getPlayerById(userId)?.name || ''; + return playersStore.getPlayerById(userId)?.name || ""; } /** @@ -364,7 +364,8 @@ export class SimplePeer { } private receiveWebrtcScreenSharingSignal(data: WebRtcSignalReceivedMessageInterface) { - if (blackListManager.isBlackListed(data.userId)) return; + const uuid = playersStore.getPlayerById(data.userId)?.userUuid || ""; + if (blackListManager.isBlackListed(uuid)) return; console.log("receiveWebrtcScreenSharingSignal", data); const streamResult = get(screenSharingLocalStreamStore); let stream: MediaStream | null = null; @@ -465,7 +466,8 @@ export class SimplePeer { } private sendLocalScreenSharingStreamToUser(userId: number, localScreenCapture: MediaStream): void { - if (blackListManager.isBlackListed(userId)) return; + const uuid = playersStore.getPlayerById(userId)?.userUuid || ""; + if (blackListManager.isBlackListed(uuid)) return; // If a connection already exists with user (because it is already sharing a screen with us... let's use this connection) if (this.PeerScreenSharingConnectionArray.has(userId)) { this.pushScreenSharingToRemoteUser(userId, localScreenCapture); diff --git a/front/src/WebRtc/VideoPeer.ts b/front/src/WebRtc/VideoPeer.ts index 30328c75..bde0bcde 100644 --- a/front/src/WebRtc/VideoPeer.ts +++ b/front/src/WebRtc/VideoPeer.ts @@ -8,6 +8,7 @@ import type { UserSimplePeerInterface } from "./SimplePeer"; import { get, readable, Readable } from "svelte/store"; import { obtainedMediaConstraintStore } from "../Stores/MediaStore"; import { discussionManager } from "./DiscussionManager"; +import { playersStore } from "../Stores/PlayersStore"; const Peer: SimplePeerNamespace.SimplePeer = require("simple-peer"); @@ -26,6 +27,7 @@ export class VideoPeer extends Peer { private remoteStream!: MediaStream; private blocked: boolean = false; public readonly userId: number; + public readonly userUuid: string; public readonly uniqueId: string; private onBlockSubscribe: Subscription; private onUnBlockSubscribe: Subscription; @@ -60,6 +62,7 @@ export class VideoPeer extends Peer { }); this.userId = user.userId; + this.userUuid = playersStore.getPlayerById(this.userId)?.userUuid || ""; this.uniqueId = "video_" + this.userId; this.streamStore = readable(null, (set) => { @@ -181,20 +184,20 @@ export class VideoPeer extends Peer { }); this.pushVideoToRemoteUser(localStream); - this.onBlockSubscribe = blackListManager.onBlockStream.subscribe((userId) => { - if (userId === this.userId) { + this.onBlockSubscribe = blackListManager.onBlockStream.subscribe((userUuid) => { + if (userUuid === this.userUuid) { this.toggleRemoteStream(false); this.sendBlockMessage(true); } }); - this.onUnBlockSubscribe = blackListManager.onUnBlockStream.subscribe((userId) => { - if (userId === this.userId) { + this.onUnBlockSubscribe = blackListManager.onUnBlockStream.subscribe((userUuid) => { + if (userUuid === this.userUuid) { this.toggleRemoteStream(true); this.sendBlockMessage(false); } }); - if (blackListManager.isBlackListed(this.userId)) { + if (blackListManager.isBlackListed(this.userUuid)) { this.sendBlockMessage(true); } } @@ -231,7 +234,7 @@ export class VideoPeer extends Peer { private stream(stream: MediaStream) { try { this.remoteStream = stream; - if (blackListManager.isBlackListed(this.userId) || this.blocked) { + if (blackListManager.isBlackListed(this.userUuid) || this.blocked) { this.toggleRemoteStream(false); } } catch (err) { diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 27d7cb10..a2e55bd8 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -62,7 +62,7 @@ message WebRtcSignalToServerMessage { } message ReportPlayerMessage { - int32 reportedUserId = 1; + string reportedUserUuid = 1; string reportComment = 2; } @@ -158,6 +158,7 @@ message UserJoinedMessage { PositionMessage position = 4; CompanionMessage companion = 5; string visitCardUrl = 6; + string userUuid = 7; } message UserLeftMessage { @@ -285,6 +286,7 @@ message UserJoinedZoneMessage { Zone fromZone = 5; CompanionMessage companion = 6; string visitCardUrl = 7; + string userUuid = 8; } message UserLeftZoneMessage { diff --git a/pusher/src/Model/Zone.ts b/pusher/src/Model/Zone.ts index 8eeeb3ef..501a2541 100644 --- a/pusher/src/Model/Zone.ts +++ b/pusher/src/Model/Zone.ts @@ -39,6 +39,7 @@ export type LeavesCallback = (thing: Movable, listener: User) => void;*/ export class UserDescriptor { private constructor( public readonly userId: number, + private userUuid: string, private name: string, private characterLayers: CharacterLayerMessage[], private position: PositionMessage, @@ -57,6 +58,7 @@ export class UserDescriptor { } return new UserDescriptor( message.getUserid(), + message.getUseruuid(), message.getName(), message.getCharacterlayersList(), position, @@ -84,6 +86,7 @@ export class UserDescriptor { userJoinedMessage.setVisitcardurl(this.visitCardUrl); } userJoinedMessage.setCompanion(this.companion); + userJoinedMessage.setUseruuid(this.userUuid); return userJoinedMessage; } diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 8a0d3673..cfac5946 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -61,7 +61,6 @@ export interface AdminSocketData { export class SocketManager implements ZoneEventListener { private rooms: Map = new Map(); - private sockets: Map = new Map(); constructor() { clientEventsEmitter.registerToClientJoin((clientUUid: string, roomId: string) => { @@ -191,8 +190,6 @@ export class SocketManager implements ZoneEventListener { .on("data", (message: ServerToClientMessage) => { if (message.hasRoomjoinedmessage()) { client.userId = (message.getRoomjoinedmessage() as RoomJoinedMessage).getCurrentuserid(); - // TODO: do we need this.sockets anymore? - this.sockets.set(client.userId, client); // If this is the first message sent, send back the viewport. this.handleViewport(client, viewport); @@ -302,14 +299,8 @@ export class SocketManager implements ZoneEventListener { async handleReportMessage(client: ExSocketInterface, reportPlayerMessage: ReportPlayerMessage) { try { - const reportedSocket = this.sockets.get(reportPlayerMessage.getReporteduserid()); - if (!reportedSocket) { - throw "reported socket user not found"; - } - //TODO report user on admin application - //todo: move to back because this fail if the reported player is in another pusher. await adminApi.reportPlayer( - reportedSocket.userUuid, + reportPlayerMessage.getReporteduseruuid(), reportPlayerMessage.getReportcomment(), client.userUuid, client.roomId.split("/")[2] @@ -334,14 +325,6 @@ export class SocketManager implements ZoneEventListener { socket.backConnection.write(pusherToBackMessage); } - private searchClientByIdOrFail(userId: number): ExSocketInterface { - const client: ExSocketInterface | undefined = this.sockets.get(userId); - if (client === undefined) { - throw new Error("Could not find user with id " + userId); - } - return client; - } - leaveRoom(socket: ExSocketInterface) { // leave previous room and world try { @@ -364,9 +347,8 @@ export class SocketManager implements ZoneEventListener { //Client.leave(Client.roomId); } finally { //delete Client.roomId; - this.sockets.delete(socket.userId); clientEventsEmitter.emitClientLeave(socket.userUuid, socket.roomId); - console.log("A user left (", this.sockets.size, " connected users)"); + console.log("A user left"); } } } finally { @@ -410,15 +392,6 @@ export class SocketManager implements ZoneEventListener { return this.rooms; } - searchClientByUuid(uuid: string): ExSocketInterface | null { - for (const socket of this.sockets.values()) { - if (socket.userUuid === uuid) { - return socket; - } - } - return null; - } - public handleQueryJitsiJwtMessage(client: ExSocketInterface, queryJitsiJwtMessage: QueryJitsiJwtMessage) { try { const room = queryJitsiJwtMessage.getJitsiroom(); From 24811e0a31a70a4d32fe3fda16d0f71274d6f872 Mon Sep 17 00:00:00 2001 From: GRL Date: Wed, 7 Jul 2021 14:59:40 +0200 Subject: [PATCH 4/5] SetProperty delete a property where tha value is undefined and load the map of exitUrl property --- front/src/Phaser/Game/GameScene.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d6df242f..6427e0c0 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1077,14 +1077,24 @@ ${escapedMessage} console.warn('Could not find layer "' + layerName + '" when calling setProperty'); return; } + if (propertyName === "exitUrl" && typeof propertyValue === "string") { + this.loadNextGame(propertyValue); + } if (layer.properties === undefined) { layer.properties = []; } const property = layer.properties.find((property) => property.name === propertyName); if (property === undefined) { + if (propertyValue === undefined) { + return; + } layer.properties.push({ name: propertyName, type: typeof propertyValue, value: propertyValue }); return; } + if (propertyValue === undefined) { + const index = layer.properties.indexOf(property); + layer.properties.splice(index, 1); + } property.value = propertyValue; } From 17525e1e158256023efda437e88a1f04f4d2bef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gr=C3=A9goire=20parant?= Date: Wed, 7 Jul 2021 16:42:26 +0200 Subject: [PATCH 5/5] Return at the new line into the Pop-up (#1267) Add regex to replace "\r\n" or "\r" or "\n" by
--- front/src/WebRtc/HtmlUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/WebRtc/HtmlUtils.ts b/front/src/WebRtc/HtmlUtils.ts index 942e553f..569abd07 100644 --- a/front/src/WebRtc/HtmlUtils.ts +++ b/front/src/WebRtc/HtmlUtils.ts @@ -25,7 +25,7 @@ export class HtmlUtils { } public static escapeHtml(html: string): string { - const text = document.createTextNode(html); + const text = document.createTextNode(html.replace(/(\r\n|\r|\n)/g,'
')); const p = document.createElement('p'); p.appendChild(text); return p.innerHTML;