From 0500ccda0f377cc2b250caad17a620fc047a4f25 Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Sat, 28 May 2022 16:58:29 +0200 Subject: [PATCH] [mirotalk] - add possibility to password protect the room --- README.md | 2 +- app/src/server.js | 64 +++++++++----- public/css/client.css | 6 +- public/js/client.js | 179 +++++++++++++++++++++++++++++++--------- public/view/client.html | 5 +- 5 files changed, 190 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index cc35b1b1..d6fd226f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ - Is `100% Free` - `Open Source` - `Self Hosted` - No download, plug-in, or login required, entirely browser-based - Unlimited number of conference rooms without call time limitation -- Possibility to Lock/Unlock the Room for the meeting +- Possibility to Password protect the Room for the meeting - Desktop and Mobile compatible - Optimized Room URL Sharing (share it to your participants, wait for them to join) - Webcam Streaming (Front - Rear for mobile) diff --git a/app/src/server.js b/app/src/server.js index b43091c4..72af4f7f 100755 --- a/app/src/server.js +++ b/app/src/server.js @@ -383,6 +383,7 @@ io.sockets.on('connect', (socket) => { log.debug('[' + socket.id + '] join ', config); let channel = config.channel; + let channel_password = config.channel_password; let peer_name = config.peer_name; let peer_video = config.peer_video; let peer_audio = config.peer_audio; @@ -400,7 +401,7 @@ io.sockets.on('connect', (socket) => { if (!(channel in peers)) peers[channel] = {}; // room locked by the participants can't join - if (peers[channel]['Locked'] === true) { + if (peers[channel]['lock'] === true && peers[channel]['password'] != channel_password) { log.debug('[' + socket.id + '] [Warning] Room Is Locked', channel); socket.emit('roomIsLocked'); return; @@ -461,16 +462,12 @@ io.sockets.on('connect', (socket) => { delete socket.channels[channel]; delete channels[channel][socket.id]; - delete peers[channel][socket.id]; + delete peers[channel][socket.id]; // delete peer data from the room switch (Object.keys(peers[channel]).length) { - case 0: - // last peer disconnected from the room without room status set, delete room data - delete peers[channel]; - break; - case 1: - // last peer disconnected from the room having room status set, delete room data - if ('Locked' in peers[channel]) delete peers[channel]; + case 0: // last peer disconnected from the room without room lock & password set + case 2: // last peer disconnected from the room having room lock & password set + delete peers[channel]; // clean lock and password value from the room break; } log.debug('connected peers grp by roomId', peers); @@ -517,21 +514,44 @@ io.sockets.on('connect', (socket) => { }); /** - * Refresh Room Status (Locked/Unlocked) + * Handle Room action */ - socket.on('roomStatus', (config) => { + socket.on('roomAction', (config) => { + //log.debug('[' + socket.id + '] Room action:', config); + let room_is_locked = false; let room_id = config.room_id; - let room_locked = config.room_locked; let peer_name = config.peer_name; - - peers[room_id]['Locked'] = room_locked; - - log.debug('[' + socket.id + '] emit roomStatus' + ' to [room_id: ' + room_id + ' locked: ' + room_locked + ']'); - - sendToRoom(room_id, socket.id, 'roomStatus', { - peer_name: peer_name, - room_locked: room_locked, - }); + let password = config.password; + let action = config.action; + // + switch (action) { + case 'lock': + peers[room_id]['lock'] = true; + peers[room_id]['password'] = password; + sendToRoom(room_id, socket.id, 'roomAction', { + peer_name: peer_name, + action: action, + }); + room_is_locked = true; + break; + case 'unlock': + peers[room_id]['lock'] = false; + peers[room_id]['password'] = password; + sendToRoom(room_id, socket.id, 'roomAction', { + peer_name: peer_name, + action: action, + }); + break; + case 'checkPassword': + let config = { + peer_name: peer_name, + action: action, + password: password === peers[room_id]['password'] ? 'OK' : 'KO', + }; + sendToPeer(socket.id, sockets, 'roomAction', config); + break; + } + log.debug('[' + socket.id + '] Room ' + room_id, { locked: room_is_locked, password: password }); }); /** @@ -573,7 +593,7 @@ io.sockets.on('connect', (socket) => { let status = config.status; for (let peer_id in peers[room_id]) { - if (peers[room_id][peer_id]['peer_name'] == peer_name) { + if (peers[room_id][peer_id]['peer_name'] === peer_name) { switch (element) { case 'video': peers[room_id][peer_id]['peer_video'] = status; diff --git a/public/css/client.css b/public/css/client.css index b5e9b13d..96abea61 100755 --- a/public/css/client.css +++ b/public/css/client.css @@ -607,7 +607,8 @@ emoji-picker { #myPeerNameSetBtn, #muteEveryoneBtn, #hideEveryoneBtn, -#lockUnlockRoomBtn, +#lockRoomBtn, +#unlockRoomBtn, #speechRecognitionStart, #speechRecognitionStop { font-size: 0.9rem; @@ -618,7 +619,8 @@ emoji-picker { } #myPeerNameSetBtn:hover, -#lockUnlockRoomBtn:hover, +#lockRoomBtn:hover, +#unlockRoomBtn:hover, #speechRecognitionStart:hover, #speechRecognitionStop:hover { color: var(--hover-color); diff --git a/public/js/client.js b/public/js/client.js index 538fd1c0..17ebf875 100644 --- a/public/js/client.js +++ b/public/js/client.js @@ -68,6 +68,8 @@ const chatInputEmoji = { ':+1:': '\uD83D\uDC4D', }; // https://github.com/wooorm/gemoji/blob/main/support.md +let thisRoomPassword = null; + let myPeerId; // socket.id // video cam - screen max frame rate @@ -238,7 +240,8 @@ let wbPop = []; // room actions btns let muteEveryoneBtn; let hideEveryoneBtn; -let lockUnlockRoomBtn; +let lockRoomBtn; +let unlockRoomBtn; // file transfer settings let fileToSend; let fileReader; @@ -387,7 +390,8 @@ function getHtmlElementsById() { // room actions buttons muteEveryoneBtn = getId('muteEveryoneBtn'); hideEveryoneBtn = getId('hideEveryoneBtn'); - lockUnlockRoomBtn = getId('lockUnlockRoomBtn'); + lockRoomBtn = getId('lockRoomBtn'); + unlockRoomBtn = getId('unlockRoomBtn'); // file send progress sendFileDiv = getId('sendFileDiv'); sendFileInfo = getId('sendFileInfo'); @@ -639,10 +643,10 @@ function initClientPeer() { // on receiving data from signaling server... signalingSocket.on('connect', handleConnect); - signalingSocket.on('serverInfo', handleServerInfo); - signalingSocket.on('roomIsLocked', handleRoomLocked); - signalingSocket.on('roomStatus', handleRoomStatus); + signalingSocket.on('roomIsLocked', handleUnlockTheRoom); + signalingSocket.on('roomAction', handleRoomAction); signalingSocket.on('addPeer', handleAddPeer); + signalingSocket.on('serverInfo', handleServerInfo); signalingSocket.on('sessionDescription', handleSessionDescription); signalingSocket.on('iceCandidate', handleIceCandidate); signalingSocket.on('peerName', handlePeerName); @@ -795,12 +799,13 @@ function whoAreYouJoin() { } /** - * join to chennel and send some peer info + * join to channel and send some peer info */ function joinToChannel() { console.log('join to channel', roomId); sendToServer('join', { channel: roomId, + channel_password: thisRoomPassword, peer_info: peerInfo, peer_geo: peerGeo, peer_name: myPeerName, @@ -2467,8 +2472,11 @@ function setupMySettings() { hideEveryoneBtn.addEventListener('click', (e) => { disableAllPeers('video'); }); - lockUnlockRoomBtn.addEventListener('click', (e) => { - lockUnlockRoom(); + lockRoomBtn.addEventListener('click', (e) => { + handleRoomAction({ action: 'lock' }, true); + }); + unlockRoomBtn.addEventListener('click', (e) => { + handleRoomAction({ action: 'unlock' }, true); }); } @@ -4309,59 +4317,100 @@ function disablePeer(peer_id, element) { } /** - * Lock Unlock the room from unauthorized access + * Handle Room action + * @param {object} config data + * @param {boolean} emit data to signaling server */ -function lockUnlockRoom() { - getId('lockUnlockRoomIco').className = roomLocked ? 'fas fa-lock-open' : 'fas fa-lock'; +function handleRoomAction(config, emit = false) { + if (emit) { + let thisConfig = { + room_id: roomId, + peer_name: myPeerName, + action: config.action, + password: null, + }; + switch (config.action) { + case 'lock': + playSound('newMessage'); - if (roomLocked) { - roomLocked = false; - emitRoomStatus(); + Swal.fire({ + allowOutsideClick: false, + allowEscapeKey: false, + showDenyButton: true, + background: swalBackground, + imageUrl: roomLockedImg, + input: 'text', + inputPlaceholder: 'Set Room password', + confirmButtonText: `OK`, + denyButtonText: `Cancel`, + showClass: { + popup: 'animate__animated animate__fadeInDown', + }, + hideClass: { + popup: 'animate__animated animate__fadeOutUp', + }, + inputValidator: (pwd) => { + if (!pwd) return 'Please enter the Room password'; + thisRoomPassword = pwd; + }, + }).then((result) => { + if (result.isConfirmed) { + thisConfig.password = thisRoomPassword; + sendToServer('roomAction', thisConfig); + handleRoomStatus(thisConfig); + } + }); + break; + case 'unlock': + sendToServer('roomAction', thisConfig); + handleRoomStatus(thisConfig); + break; + } } else { - roomLocked = true; - emitRoomStatus(); - playSound('locked'); + // data coming from signaling server + handleRoomStatus(config); } } /** - * Refresh Room Status (Locked/Unlocked) - */ -function emitRoomStatus() { - let rStatus = roomLocked ? '🔒 LOCKED the room, no one can access!' : '🔓 UNLOCKED the room'; - userLog('toast', rStatus); - - sendToServer('roomStatus', { - room_id: roomId, - room_locked: roomLocked, - peer_name: myPeerName, - }); -} - -/** - * Handle Room Status (Lock - Unlock) + * Handle room status * @param {object} config data */ function handleRoomStatus(config) { + let action = config.action; let peer_name = config.peer_name; - let room_locked = config.room_locked; - roomLocked = room_locked; - lockUnlockRoomBtn.className = roomLocked ? 'fas fa-lock' : 'fas fa-lock-open'; - userLog('toast', peer_name + ' set room is locked to ' + roomLocked); + switch (action) { + case 'lock': + playSound('locked'); + userLog('toast', peer_name + ' has 🔒 LOCKED the room by password', 'top-end'); + hide(lockRoomBtn); + show(unlockRoomBtn); + break; + case 'unlock': + userLog('toast', peer_name + ' has 🔓 UNLOCKED the room', 'top-end'); + hide(unlockRoomBtn); + show(lockRoomBtn); + break; + case 'checkPassword': + let password = config.password; + password == 'OK' ? joinToChannel() : handleRoomLocked(); + break; + } } /** - * Room is Locked can't access... + * Room is locked you provide a wrong password, can't access! */ function handleRoomLocked() { playSound('kickedOut'); + console.log('Room is Locked, try with another one'); Swal.fire({ allowOutsideClick: false, background: swalBackground, position: 'center', imageUrl: roomLockedImg, - title: 'Oops, Room Locked', + title: 'Oops, Wrong Room Password', text: 'The room is locked, try with another one.', showDenyButton: false, confirmButtonText: `Ok`, @@ -4376,6 +4425,44 @@ function handleRoomLocked() { }); } +/** + * Try to unlock the room by providing a valid password + */ +function handleUnlockTheRoom() { + playSound('alert'); + + Swal.fire({ + allowOutsideClick: false, + allowEscapeKey: false, + background: swalBackground, + imageUrl: roomLockedImg, + title: 'Oops, Room is Locked', + input: 'text', + inputPlaceholder: 'Enter the Room password', + confirmButtonText: `OK`, + showClass: { + popup: 'animate__animated animate__fadeInDown', + }, + hideClass: { + popup: 'animate__animated animate__fadeOutUp', + }, + inputValidator: (pwd) => { + if (!pwd) return 'Please enter the Room password'; + thisRoomPassword = pwd; + }, + }).then(() => { + let config = { + room_id: roomId, + peer_name: myPeerName, + action: 'checkPassword', + password: thisRoomPassword, + }; + sendToServer('roomAction', config); + hide(lockRoomBtn); + show(unlockRoomBtn); + }); +} + /** * Handle whiteboard toogle */ @@ -5677,3 +5764,19 @@ function getSl(selector) { function getEcN(className) { return document.getElementsByClassName(className); } + +/** + * Hide elemnt + * @param {object} elem + */ +function hide(elem) { + elem.className = 'hidden'; +} + +/** + * Show elemnt + * @param {object} elem + */ +function show(elem) { + elem.className = ''; +} diff --git a/public/view/client.html b/public/view/client.html index 098e7853..c5cf36cf 100755 --- a/public/view/client.html +++ b/public/view/client.html @@ -282,9 +282,8 @@ access to use this app.


- + +