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.
-
+
+