[mirotalksfu] - Fix Room Password & Lobby
هذا الالتزام موجود في:
@@ -108,13 +108,14 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
- You can `directly join a room` by using link like:
|
- You can `directly join a room` by using link like:
|
||||||
- https://sfu.mirotalk.com/join?room=test&roomPassword=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0&duration=unlimited
|
- https://sfu.mirotalk.com/join?room=test&roomPassword=0&name=mirotalksfu&avatar=0&audio=0&video=0&screen=0¬ify=0&duration=unlimited
|
||||||
|
|
||||||
| Params | Type | Description |
|
| Params | Type | Description |
|
||||||
| ------------ | -------------- | ------------------------- |
|
| ------------ | -------------- | ------------------------- |
|
||||||
| room | string | Room Id |
|
| room | string | Room Id |
|
||||||
| roomPassword | string/boolean | Room password |
|
| roomPassword | string/boolean | Room password |
|
||||||
| name | string | User name |
|
| name | string | User name |
|
||||||
|
| avatar | string/boolean | User avatar |
|
||||||
| audio | boolean | Audio stream |
|
| audio | boolean | Audio stream |
|
||||||
| video | boolean | Video stream |
|
| video | boolean | Video stream |
|
||||||
| screen | boolean | Screen stream |
|
| screen | boolean | Screen stream |
|
||||||
|
|||||||
@@ -603,6 +603,7 @@ module.exports = class Room {
|
|||||||
iceState: iceState,
|
iceState: iceState,
|
||||||
});
|
});
|
||||||
this.removePeer(socket_id);
|
this.removePeer(socket_id);
|
||||||
|
transport.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -622,6 +623,7 @@ module.exports = class Room {
|
|||||||
dtlsState: dtlsState,
|
dtlsState: dtlsState,
|
||||||
});
|
});
|
||||||
this.removePeer(socket_id);
|
this.removePeer(socket_id);
|
||||||
|
transport.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ dev dependencies: {
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
||||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.8.13
|
* @version 1.8.14
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mirotalksfu",
|
"name": "mirotalksfu",
|
||||||
"version": "1.8.13",
|
"version": "1.8.14",
|
||||||
"description": "WebRTC SFU browser-based video calls",
|
"description": "WebRTC SFU browser-based video calls",
|
||||||
"main": "Server.js",
|
"main": "Server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mattermost/client": "10.6.0",
|
"@mattermost/client": "10.6.0",
|
||||||
"@ngrok/ngrok": "1.4.1",
|
"@ngrok/ngrok": "1.4.1",
|
||||||
"@sentry/node": "^9.11.0",
|
"@sentry/node": "^9.12.0",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
"colors": "1.4.0",
|
"colors": "1.4.0",
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
"mediasoup": "3.15.7",
|
"mediasoup": "3.15.7",
|
||||||
"mediasoup-client": "3.9.5",
|
"mediasoup-client": "3.9.5",
|
||||||
"nodemailer": "^6.10.0",
|
"nodemailer": "^6.10.0",
|
||||||
"openai": "^4.92.1",
|
"openai": "^4.93.0",
|
||||||
"qs": "6.14.0",
|
"qs": "6.14.0",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"socket.io": "4.8.1",
|
"socket.io": "4.8.1",
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
"proxyquire": "^2.1.3",
|
"proxyquire": "^2.1.3",
|
||||||
"should": "^13.2.3",
|
"should": "^13.2.3",
|
||||||
"sinon": "^20.0.0",
|
"sinon": "^20.0.0",
|
||||||
"webpack": "^5.99.1",
|
"webpack": "^5.99.5",
|
||||||
"webpack-cli": "^6.0.1"
|
"webpack-cli": "^6.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ let BRAND = {
|
|||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
imageUrl: '../images/mirotalk-logo.gif',
|
imageUrl: '../images/mirotalk-logo.gif',
|
||||||
title: '<strong>WebRTC SFU v1.8.13</strong>',
|
title: '<strong>WebRTC SFU v1.8.14</strong>',
|
||||||
html: `
|
html: `
|
||||||
<button
|
<button
|
||||||
id="support-button"
|
id="support-button"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
||||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.8.13
|
* @version 1.8.14
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -5351,7 +5351,7 @@ function showAbout() {
|
|||||||
position: 'center',
|
position: 'center',
|
||||||
imageUrl: BRAND.about?.imageUrl && BRAND.about.imageUrl.trim() !== '' ? BRAND.about.imageUrl : image.about,
|
imageUrl: BRAND.about?.imageUrl && BRAND.about.imageUrl.trim() !== '' ? BRAND.about.imageUrl : image.about,
|
||||||
customClass: { image: 'img-about' },
|
customClass: { image: 'img-about' },
|
||||||
title: BRAND.about?.title && BRAND.about.title.trim() !== '' ? BRAND.about.title : 'WebRTC SFU v1.8.13',
|
title: BRAND.about?.title && BRAND.about.title.trim() !== '' ? BRAND.about.title : 'WebRTC SFU v1.8.14',
|
||||||
html: `
|
html: `
|
||||||
<br />
|
<br />
|
||||||
<div id="about">
|
<div id="about">
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
||||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.8.13
|
* @version 1.8.14
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -339,7 +339,14 @@ class RoomClient {
|
|||||||
this.localAudioStream = null;
|
this.localAudioStream = null;
|
||||||
this.localScreenStream = null;
|
this.localScreenStream = null;
|
||||||
|
|
||||||
|
// Room Password
|
||||||
|
this.RoomIsLocked = false;
|
||||||
this.RoomPassword = false;
|
this.RoomPassword = false;
|
||||||
|
this.RoomPasswordValid = false;
|
||||||
|
|
||||||
|
// Room Lobby
|
||||||
|
this.RoomIsLobby = false;
|
||||||
|
this.RoomLobbyAccepted = false;
|
||||||
|
|
||||||
this.transcription = transcription;
|
this.transcription = transcription;
|
||||||
|
|
||||||
@@ -455,50 +462,53 @@ class RoomClient {
|
|||||||
.request('join', data)
|
.request('join', data)
|
||||||
.then(async (room) => {
|
.then(async (room) => {
|
||||||
console.log('##### JOIN ROOM #####', room);
|
console.log('##### JOIN ROOM #####', room);
|
||||||
|
|
||||||
if (room === 'invalid') {
|
if (room === 'invalid') {
|
||||||
console.log('00-WARNING ----> Invalid Room name! Path traversal pattern detected!');
|
console.warn('00-WARNING ----> Invalid Room name! Path traversal pattern detected!');
|
||||||
return this.roomInvalid();
|
return this.roomInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room === 'notAllowed') {
|
if (room === 'notAllowed') {
|
||||||
console.log(
|
console.warn(
|
||||||
'00-WARNING ----> Room is Unauthorized for current user, please provide a valid room name for this user',
|
'00-WARNING ----> Room is Unauthorized for current user, please provide a valid room name for this user',
|
||||||
);
|
);
|
||||||
return this.userRoomNotAllowed();
|
return this.userRoomNotAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room === 'unauthorized') {
|
if (room === 'unauthorized') {
|
||||||
console.log(
|
console.warn(
|
||||||
'00-WARNING ----> Room is Unauthorized for current user, please provide a valid username and password',
|
'00-WARNING ----> Room is Unauthorized for current user, please provide a valid username and password',
|
||||||
);
|
);
|
||||||
return this.userUnauthorized();
|
return this.userUnauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room === 'isLocked') {
|
if (room === 'isLocked') {
|
||||||
|
this.RoomIsLocked = true;
|
||||||
this.event(_EVENTS.roomLock);
|
this.event(_EVENTS.roomLock);
|
||||||
console.log('00-WARNING ----> Room is Locked, Try to unlock by the password');
|
console.warn('00-WARNING ----> Room is Locked, Try to unlock by the password');
|
||||||
return this.unlockTheRoom();
|
return this.unlockTheRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room === 'isLobby') {
|
if (room === 'isLobby') {
|
||||||
|
this.RoomIsLobby = true;
|
||||||
this.event(_EVENTS.lobbyOn);
|
this.event(_EVENTS.lobbyOn);
|
||||||
console.log('00-WARNING ----> Room Lobby Enabled, Wait to confirm my join');
|
console.warn('00-WARNING ----> Room Lobby Enabled, Wait to confirm my join');
|
||||||
return this.waitJoinConfirm();
|
return this.waitJoinConfirm();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room === 'isBanned') {
|
if (room === 'isBanned') {
|
||||||
console.log('00-WARNING ----> You are Banned from the Room!');
|
console.warn('00-WARNING ----> You are Banned from the Room!');
|
||||||
return this.isBanned();
|
return this.isBanned();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ##########################################
|
// ##########################################
|
||||||
this.peers = new Map(JSON.parse(room.peers));
|
this.peers = new Map(JSON.parse(room.peers));
|
||||||
// ##########################################
|
// ##########################################
|
||||||
|
|
||||||
if (!peer_info.peer_token) {
|
if (this.usernameExists(this.peers)) {
|
||||||
// hack...
|
return this.userNameAlreadyInRoom();
|
||||||
for (let peer of Array.from(this.peers.keys()).filter((id) => id !== this.peer_id)) {
|
|
||||||
let peer_info = this.peers.get(peer).peer_info;
|
|
||||||
if (peer_info.peer_name == this.peer_name) {
|
|
||||||
console.log('00-WARNING ----> Username already in use');
|
|
||||||
return this.userNameAlreadyInRoom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.joinAllowed(room);
|
await this.joinAllowed(room);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -508,19 +518,31 @@ class RoomClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usernameExists(peers) {
|
||||||
|
if (!peer_info.peer_token) {
|
||||||
|
// hack...
|
||||||
|
for (let peer of Array.from(peers.keys()).filter((id) => id !== this.peer_id)) {
|
||||||
|
let peer_info = peers.get(peer).peer_info;
|
||||||
|
if (peer_info.peer_name == this.peer_name) {
|
||||||
|
console.log('07.0-WARNING ----> Username already in use');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
async joinAllowed(room) {
|
async joinAllowed(room) {
|
||||||
console.log('07 ----> Join Room allowed');
|
console.log('07 ----> Join Room allowed');
|
||||||
|
|
||||||
await this.handleRoomInfo(room);
|
await this.handleRoomInfo(room);
|
||||||
const routerRtpCapabilities = await this.socket.request('getRouterRtpCapabilities');
|
|
||||||
routerRtpCapabilities.headerExtensions = routerRtpCapabilities.headerExtensions.filter(
|
await this.loadDeviceAndInitTransports();
|
||||||
(ext) => ext.uri !== 'urn:3gpp:video-orientation',
|
|
||||||
);
|
// ###############################################
|
||||||
this.device = await this.loadDevice(routerRtpCapabilities);
|
this.socket.emit('getProducers'); // newProducers
|
||||||
console.log('07.3 ----> Get Router Rtp Capabilities codecs: ', this.device.rtpCapabilities.codecs);
|
// ###############################################
|
||||||
await this.initTransports(this.device);
|
|
||||||
// ###################################
|
|
||||||
this.socket.emit('getProducers');
|
|
||||||
// ###################################
|
|
||||||
if (isBroadcastingEnabled) {
|
if (isBroadcastingEnabled) {
|
||||||
isPresenter ? await this.startLocalMedia() : this.handleRoomBroadcasting();
|
isPresenter ? await this.startLocalMedia() : this.handleRoomBroadcasting();
|
||||||
} else {
|
} else {
|
||||||
@@ -528,12 +550,34 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async loadDeviceAndInitTransports() {
|
||||||
|
// Get Router Capabilities
|
||||||
|
const routerRtpCapabilities = await this.socket.request('getRouterRtpCapabilities');
|
||||||
|
routerRtpCapabilities.headerExtensions = routerRtpCapabilities.headerExtensions.filter(
|
||||||
|
(ext) => ext.uri !== 'urn:3gpp:video-orientation',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load device
|
||||||
|
this.device = await this.loadDevice(routerRtpCapabilities);
|
||||||
|
console.log('07.3 ----> Get Router Rtp Capabilities codecs: ', this.device.rtpCapabilities.codecs);
|
||||||
|
|
||||||
|
// Init Send/Receive Transports
|
||||||
|
await this.initTransports(this.device);
|
||||||
|
}
|
||||||
|
|
||||||
async handleRoomInfo(room) {
|
async handleRoomInfo(room) {
|
||||||
|
// ##########################################
|
||||||
|
this.peers = new Map(JSON.parse(room.peers));
|
||||||
|
// ##########################################
|
||||||
|
|
||||||
console.log('07.0 ----> Room Survey', room.survey);
|
console.log('07.0 ----> Room Survey', room.survey);
|
||||||
survey = room.survey;
|
survey = room.survey;
|
||||||
|
|
||||||
console.log('07.0 ----> Room Leave Redirect', room.redirect);
|
console.log('07.0 ----> Room Leave Redirect', room.redirect);
|
||||||
redirect = room.redirect;
|
redirect = room.redirect;
|
||||||
|
|
||||||
participantsCount = this.peers.size;
|
participantsCount = this.peers.size;
|
||||||
|
|
||||||
// ME
|
// ME
|
||||||
for (let peer of Array.from(this.peers.keys()).filter((id) => id == this.peer_id)) {
|
for (let peer of Array.from(this.peers.keys()).filter((id) => id == this.peer_id)) {
|
||||||
let my_peer_info = this.peers.get(peer).peer_info;
|
let my_peer_info = this.peers.get(peer).peer_info;
|
||||||
@@ -1075,7 +1119,28 @@ class RoomClient {
|
|||||||
|
|
||||||
handleNewProducers = async (data) => {
|
handleNewProducers = async (data) => {
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
console.log('SocketOn New producers', data);
|
console.log('SocketOn New producers', {
|
||||||
|
data,
|
||||||
|
password: {
|
||||||
|
roomIsLocked: this.RoomIsLocked,
|
||||||
|
roomPasswordValid: this.RoomPasswordValid,
|
||||||
|
},
|
||||||
|
lobby: {
|
||||||
|
roomIsLobby: this.RoomIsLobby,
|
||||||
|
roomLobbyAccepted: this.RoomLobbyAccepted,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.RoomIsLocked && !this.RoomPasswordValid) {
|
||||||
|
console.log('Access denied: Room is locked and password has not been validated yet', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.RoomIsLobby && !this.RoomLobbyAccepted) {
|
||||||
|
console.log('Access pending: Lobby mode is active, waiting for approval to join', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (let { producer_id, peer_name, peer_info, type } of data) {
|
for (let { producer_id, peer_name, peer_info, type } of data) {
|
||||||
await this.consume(producer_id, peer_name, peer_info, type);
|
await this.consume(producer_id, peer_name, peer_info, type);
|
||||||
}
|
}
|
||||||
@@ -2735,6 +2800,15 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getConsumeStream(producerId, peer_id, type) {
|
async getConsumeStream(producerId, peer_id, type) {
|
||||||
|
if (!this.device) {
|
||||||
|
throw new Error('Device not initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if consumer transport exists
|
||||||
|
if (!this.consumerTransport) {
|
||||||
|
throw new Error('Consumer transport not initialized');
|
||||||
|
}
|
||||||
|
|
||||||
const { rtpCapabilities } = this.device;
|
const { rtpCapabilities } = this.device;
|
||||||
|
|
||||||
const data = await this.socket.request('consume', {
|
const data = await this.socket.request('consume', {
|
||||||
@@ -7303,13 +7377,14 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
roomPassword(data) {
|
async roomPassword(data) {
|
||||||
switch (data.password) {
|
switch (data.password) {
|
||||||
case 'OK':
|
case 'OK':
|
||||||
this.joinAllowed(data.room);
|
this.RoomPasswordValid = true;
|
||||||
handleRules(isPresenter);
|
await this.joinAllowed(data.room);
|
||||||
break;
|
break;
|
||||||
case 'KO':
|
case 'KO':
|
||||||
|
this.RoomPasswordValid = false;
|
||||||
this.roomIsLocked();
|
this.roomIsLocked();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -7335,7 +7410,7 @@ class RoomClient {
|
|||||||
peer_avatar && this.isImageURL(peer_avatar)
|
peer_avatar && this.isImageURL(peer_avatar)
|
||||||
? peer_avatar
|
? peer_avatar
|
||||||
: this.isValidEmail(peer_name)
|
: this.isValidEmail(peer_name)
|
||||||
? this.genGravatar(peer_name)
|
? this.genGravatar(peer_name, 32)
|
||||||
: this.genAvatarSvg(peer_name, 32);
|
: this.genAvatarSvg(peer_name, 32);
|
||||||
|
|
||||||
let lobbyTb = this.getId('lobbyTb');
|
let lobbyTb = this.getId('lobbyTb');
|
||||||
@@ -7365,13 +7440,14 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'accept':
|
case 'accept':
|
||||||
|
this.RoomLobbyAccepted = true;
|
||||||
await this.joinAllowed(data.room);
|
await this.joinAllowed(data.room);
|
||||||
handleRules(isPresenter);
|
|
||||||
control.style.display = 'flex';
|
control.style.display = 'flex';
|
||||||
bottomButtons.style.display = 'flex';
|
bottomButtons.style.display = 'flex';
|
||||||
this.msgPopup('info', 'Your join meeting request was accepted by the moderator');
|
this.msgPopup('info', 'Your join meeting request was accepted by the moderator', 3000, 'top');
|
||||||
break;
|
break;
|
||||||
case 'reject':
|
case 'reject':
|
||||||
|
this.RoomLobbyAccepted = false;
|
||||||
this.sound('eject');
|
this.sound('eject');
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'warning',
|
icon: 'warning',
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم