[mirotalksfu] - add JWT, update dep
هذا الالتزام موجود في:
16
README.md
16
README.md
@@ -37,6 +37,7 @@
|
|||||||
- Translated into 133 languages.
|
- Translated into 133 languages.
|
||||||
- Host protection to prevent unauthorized access.
|
- Host protection to prevent unauthorized access.
|
||||||
- User auth to prevent unauthorized access.
|
- User auth to prevent unauthorized access.
|
||||||
|
- JWT.io securely manages credentials for host configurations and user authentication, enhancing security and streamlining processes.
|
||||||
- Room password protection.
|
- Room password protection.
|
||||||
- Room lobby, central gathering space.
|
- Room lobby, central gathering space.
|
||||||
- Room spam mitigations, focused on preventing spam.
|
- Room spam mitigations, focused on preventing spam.
|
||||||
@@ -97,11 +98,7 @@
|
|||||||
| screen | boolean | Screen stream |
|
| screen | boolean | Screen stream |
|
||||||
| notify | boolean | Welcome message |
|
| notify | boolean | Welcome message |
|
||||||
| hide | boolean | Hide myself |
|
| hide | boolean | Hide myself |
|
||||||
| username | string | Auth username |
|
| token | string | JWT |
|
||||||
| password | string | Auth password |
|
|
||||||
|
|
||||||
> **Caution**
|
|
||||||
> It is strongly advised against including usernames and passwords in URL parameters for security reasons.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -110,7 +107,7 @@
|
|||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
When [host.protected](https://docs.mirotalk.com/mirotalk-sfu/host-protection/) or `host.user_auth` is enabled, the host/users must provide a valid username and password for joining the room as specified in the `app/src/config.js` file.
|
When [host.protected](https://docs.mirotalk.com/mirotalk-sfu/host-protection/) or `host.user_auth` is enabled, the host/users can provide a valid token for direct joining the room as specified in the `app/src/config.js` file.
|
||||||
|
|
||||||
| Params | Value | Description |
|
| Params | Value | Description |
|
||||||
| ---------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
| ---------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
||||||
@@ -253,8 +250,11 @@ $ docker-compose down
|
|||||||
$ curl -X POST "http://localhost:3010/api/v1/meeting" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json"
|
$ curl -X POST "http://localhost:3010/api/v1/meeting" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json"
|
||||||
$ curl -X POST "https://sfu.mirotalk.com/api/v1/meeting" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json"
|
$ curl -X POST "https://sfu.mirotalk.com/api/v1/meeting" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json"
|
||||||
# The response will give you a entrypoint / URL for the direct join to the meeting.
|
# The response will give you a entrypoint / URL for the direct join to the meeting.
|
||||||
$ curl -X POST "http://localhost:3010/api/v1/join" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json" --data '{"room":"test","password":"false","name":"mirotalksfu","audio":"false","video":"false","screen":"false","notify":"false"}'
|
$ curl -X POST "http://localhost:3010/api/v1/join" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json" --data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"false","video":"false","screen":"false","notify":"false"}'
|
||||||
$ curl -X POST "https://sfu.mirotalk.com/api/v1/join" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json" --data '{"room":"test","password":"false","name":"mirotalksfu","audio":"false","video":"false","screen":"false","notify":"false"}'
|
$ curl -X POST "https://sfu.mirotalk.com/api/v1/join" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json" --data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"false","video":"false","screen":"false","notify":"false"}'
|
||||||
|
# The response will give you a entrypoint / URL for the direct join to the meeting with a token.
|
||||||
|
$ curl -X POST "http://localhost:3010/api/v1/join" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json" --data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"false","video":"false","screen":"false","notify":"false","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}'
|
||||||
|
$ curl -X POST "https://sfu.mirotalk.com/api/v1/join" -H "authorization: mirotalksfu_default_secret" -H "Content-Type: application/json" --data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"false","video":"false","screen":"false","notify":"false","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ async function getJoin() {
|
|||||||
|
|
||||||
const API_KEY_SECRET = 'mirotalksfu_default_secret';
|
const API_KEY_SECRET = 'mirotalksfu_default_secret';
|
||||||
const MIROTALK_URL = 'https://sfu.mirotalk.com/api/v1/join';
|
const MIROTALK_URL = 'https://sfu.mirotalk.com/api/v1/join';
|
||||||
// const MIROTALK_URL = 'http://localhost:3010/api/v1/join';
|
//const MIROTALK_URL = 'http://localhost:3010/api/v1/join';
|
||||||
|
|
||||||
const response = await fetch(MIROTALK_URL, {
|
const response = await fetch(MIROTALK_URL, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -24,6 +24,12 @@ async function getJoin() {
|
|||||||
screen: true,
|
screen: true,
|
||||||
hide: false,
|
hide: false,
|
||||||
notify: true,
|
notify: true,
|
||||||
|
token: {
|
||||||
|
username: 'username',
|
||||||
|
password: 'password',
|
||||||
|
presenter: true,
|
||||||
|
expire: '1h',
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ $data = array(
|
|||||||
"screen" => true,
|
"screen" => true,
|
||||||
"hide" => false,
|
"hide" => false,
|
||||||
"notify" => true,
|
"notify" => true,
|
||||||
|
"token" => array(
|
||||||
|
"username" => "username",
|
||||||
|
"password" => "password",
|
||||||
|
"presenter" => true,
|
||||||
|
"expire" => "1h",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
$data_string = json_encode($data);
|
$data_string = json_encode($data);
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ data = {
|
|||||||
"screen": "true",
|
"screen": "true",
|
||||||
"hide": "false",
|
"hide": "false",
|
||||||
"notify": "true",
|
"notify": "true",
|
||||||
|
"token": {
|
||||||
|
"username": "username",
|
||||||
|
"password": "password",
|
||||||
|
"presenter": "true",
|
||||||
|
"expire": "1h",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ MIROTALK_URL="https://sfu.mirotalk.com/api/v1/join"
|
|||||||
curl $MIROTALK_URL \
|
curl $MIROTALK_URL \
|
||||||
--header "authorization: $API_KEY_SECRET" \
|
--header "authorization: $API_KEY_SECRET" \
|
||||||
--header "Content-Type: application/json" \
|
--header "Content-Type: application/json" \
|
||||||
--data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"true","video":"true","screen":"false","hide":"false","notify":"true"}' \
|
--data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"true","video":"true","screen":"false","hide":"false","notify":"true","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}' \
|
||||||
--request POST
|
--request POST
|
||||||
@@ -18,6 +18,7 @@ dependencies: {
|
|||||||
crypto-js : https://www.npmjs.com/package/crypto-js
|
crypto-js : https://www.npmjs.com/package/crypto-js
|
||||||
express : https://www.npmjs.com/package/express
|
express : https://www.npmjs.com/package/express
|
||||||
httpolyglot : https://www.npmjs.com/package/httpolyglot
|
httpolyglot : https://www.npmjs.com/package/httpolyglot
|
||||||
|
jsonwebtoken : https://www.npmjs.com/package/jsonwebtoken
|
||||||
mediasoup : https://www.npmjs.com/package/mediasoup
|
mediasoup : https://www.npmjs.com/package/mediasoup
|
||||||
mediasoup-client : https://www.npmjs.com/package/mediasoup-client
|
mediasoup-client : https://www.npmjs.com/package/mediasoup-client
|
||||||
ngrok : https://www.npmjs.com/package/ngrok
|
ngrok : https://www.npmjs.com/package/ngrok
|
||||||
@@ -40,7 +41,7 @@ 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.3.65
|
* @version 1.3.66
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ const http = require('http');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
const ngrok = require('ngrok');
|
const ngrok = require('ngrok');
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const checkXSS = require('./XSS.js');
|
const checkXSS = require('./XSS.js');
|
||||||
@@ -92,6 +94,11 @@ const io = require('socket.io')(httpsServer, {
|
|||||||
});
|
});
|
||||||
const host = 'https://' + 'localhost' + ':' + config.server.listen.port; // config.server.listen.ip
|
const host = 'https://' + 'localhost' + ':' + config.server.listen.port; // config.server.listen.ip
|
||||||
|
|
||||||
|
const jwtCfg = {
|
||||||
|
JWT_KEY: (config.jwt && config.jwt.key) || 'mirotalksfu_jwt_secret',
|
||||||
|
JWT_EXP: (config.jwt && config.jwt.exp) || '1h',
|
||||||
|
};
|
||||||
|
|
||||||
const hostCfg = {
|
const hostCfg = {
|
||||||
protected: config.host.protected,
|
protected: config.host.protected,
|
||||||
user_auth: config.host.user_auth,
|
user_auth: config.host.user_auth,
|
||||||
@@ -279,21 +286,40 @@ function startServer() {
|
|||||||
log.debug('Direct Join', req.query);
|
log.debug('Direct Join', req.query);
|
||||||
|
|
||||||
// http://localhost:3010/join?room=test&roomPassword=0&name=mirotalksfu&audio=1&video=1&screen=0&hide=0¬ify=1
|
// http://localhost:3010/join?room=test&roomPassword=0&name=mirotalksfu&audio=1&video=1&screen=0&hide=0¬ify=1
|
||||||
// http://localhost:3010/join?room=test&roomPassword=0&name=mirotalksfu&audio=1&video=1&screen=0&hide=0¬ify=0&username=username&password=password
|
// http://localhost:3010/join?room=test&roomPassword=0&name=mirotalksfu&audio=1&video=1&screen=0&hide=0¬ify=0&token=token
|
||||||
|
|
||||||
const { room, roomPassword, name, audio, video, screen, hide, notify, username, password, isPresenter } =
|
const { room, roomPassword, name, audio, video, screen, hide, notify, token, isPresenter } = checkXSS(
|
||||||
checkXSS(req.query);
|
req.query,
|
||||||
|
);
|
||||||
|
|
||||||
const isPeerValid = isAuthPeer(username, password);
|
let peerUsername,
|
||||||
|
peerPassword = '';
|
||||||
|
let isPeerValid = false;
|
||||||
|
let isPeerPresenter = false;
|
||||||
|
|
||||||
if (hostCfg.protected && isPeerValid && !hostCfg.authenticated) {
|
if (token) {
|
||||||
|
try {
|
||||||
|
const { username, password, presenter } = checkXSS(jwt.verify(token, jwtCfg.JWT_KEY));
|
||||||
|
peerUsername = username;
|
||||||
|
peerPassword = password;
|
||||||
|
isPeerValid = isAuthPeer(username, password);
|
||||||
|
isPeerPresenter = presenter === '1' || presenter === 'true';
|
||||||
|
} catch (err) {
|
||||||
|
log.error('Direct Join JWT error', { error: err.message, token: token });
|
||||||
|
return hostCfg.protected || hostCfg.user_auth
|
||||||
|
? res.sendFile(views.login)
|
||||||
|
: res.sendFile(views.landing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostCfg.protected && isPeerValid && isPeerPresenter && !hostCfg.authenticated) {
|
||||||
const ip = getIP(req);
|
const ip = getIP(req);
|
||||||
hostCfg.authenticated = true;
|
hostCfg.authenticated = true;
|
||||||
authHost.setAuthorizedIP(ip, true);
|
authHost.setAuthorizedIP(ip, true);
|
||||||
log.debug('Direct Join user auth as host done', {
|
log.debug('Direct Join user auth as host done', {
|
||||||
ip: ip,
|
ip: ip,
|
||||||
username: username,
|
username: peerUsername,
|
||||||
password: password,
|
password: peerPassword,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,12 +412,18 @@ function startServer() {
|
|||||||
authorized: authHost.isAuthorizedIP(ip),
|
authorized: authHost.isAuthorizedIP(ip),
|
||||||
authorizedIps: authHost.getAuthorizedIPs(),
|
authorizedIps: authHost.getAuthorizedIPs(),
|
||||||
});
|
});
|
||||||
return res.status(200).json({ message: 'authorized' });
|
const token = jwt.sign({ username: username, password: password, presenter: true }, jwtCfg.JWT_KEY, {
|
||||||
|
expiresIn: jwtCfg.JWT_EXP,
|
||||||
|
});
|
||||||
|
return res.status(200).json({ message: token });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPeerValid) {
|
if (isPeerValid) {
|
||||||
log.debug('PEER LOGIN OK', { ip: ip, authorized: true });
|
log.debug('PEER LOGIN OK', { ip: ip, authorized: true });
|
||||||
return res.status(200).json({ message: 'authorized' });
|
const token = jwt.sign({ username: username, password: password, presenter: false }, jwtCfg.JWT_KEY, {
|
||||||
|
expiresIn: jwtCfg.JWT_EXP,
|
||||||
|
});
|
||||||
|
return res.status(200).json({ message: token });
|
||||||
} else {
|
} else {
|
||||||
return res.status(401).json({ message: 'unauthorized' });
|
return res.status(401).json({ message: 'unauthorized' });
|
||||||
}
|
}
|
||||||
@@ -505,6 +537,7 @@ function startServer() {
|
|||||||
app_version: packageJson.version,
|
app_version: packageJson.version,
|
||||||
node_version: process.versions.node,
|
node_version: process.versions.node,
|
||||||
hostConfig: hostCfg,
|
hostConfig: hostCfg,
|
||||||
|
jwtCfg: jwtCfg,
|
||||||
presenters: config.presenters,
|
presenters: config.presenters,
|
||||||
middleware: config.middleware,
|
middleware: config.middleware,
|
||||||
announced_ip: announcedIP,
|
announced_ip: announcedIP,
|
||||||
@@ -553,6 +586,7 @@ function startServer() {
|
|||||||
app_version: packageJson.version,
|
app_version: packageJson.version,
|
||||||
node_version: process.versions.node,
|
node_version: process.versions.node,
|
||||||
hostConfig: hostCfg,
|
hostConfig: hostCfg,
|
||||||
|
jwtCfg: jwtCfg,
|
||||||
presenters: config.presenters,
|
presenters: config.presenters,
|
||||||
middleware: config.middleware,
|
middleware: config.middleware,
|
||||||
announced_ip: announcedIP,
|
announced_ip: announcedIP,
|
||||||
@@ -990,21 +1024,38 @@ function startServer() {
|
|||||||
|
|
||||||
log.info('User joined', data);
|
log.info('User joined', data);
|
||||||
|
|
||||||
|
let is_presenter = true;
|
||||||
|
|
||||||
|
const { peer_token } = data.peer_info;
|
||||||
|
|
||||||
// User Auth required, we check if peer valid
|
// User Auth required, we check if peer valid
|
||||||
if (hostCfg.user_auth) {
|
if (hostCfg.user_auth) {
|
||||||
const { peer_username, peer_password } = data.peer_info;
|
// Check JWT
|
||||||
|
if (peer_token) {
|
||||||
|
try {
|
||||||
|
const { username, password, presenter } = checkXSS(jwt.verify(peer_token, jwtCfg.JWT_KEY));
|
||||||
|
|
||||||
const isPeerValid = isAuthPeer(peer_username, peer_password);
|
const isPeerValid = isAuthPeer(username, password);
|
||||||
|
|
||||||
log.debug('[Join] - HOST PROTECTED - USER AUTH check peer', {
|
is_presenter = presenter === '1' || presenter === 'true';
|
||||||
ip: peer_ip,
|
|
||||||
peer_username: peer_username,
|
|
||||||
peer_password: peer_password,
|
|
||||||
peer_valid: isPeerValid,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isPeerValid) {
|
log.debug('[Join] - HOST PROTECTED - USER AUTH check peer', {
|
||||||
// redirect peer to login page
|
ip: peer_ip,
|
||||||
|
peer_username: username,
|
||||||
|
peer_password: password,
|
||||||
|
peer_valid: isPeerValid,
|
||||||
|
peer_presenter: is_presenter,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isPeerValid) {
|
||||||
|
// redirect peer to login page
|
||||||
|
return cb('unauthorized');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
log.error('[Join] - JWT error', { error: err.message, token: peer_token });
|
||||||
|
return cb('unauthorized');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return cb('unauthorized');
|
return cb('unauthorized');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1048,7 +1099,7 @@ function startServer() {
|
|||||||
peer_ip: peer_ip,
|
peer_ip: peer_ip,
|
||||||
peer_name: peer_name,
|
peer_name: peer_name,
|
||||||
peer_uuid: peer_uuid,
|
peer_uuid: peer_uuid,
|
||||||
is_presenter: true,
|
is_presenter: is_presenter,
|
||||||
};
|
};
|
||||||
// first we check if the username match the presenters username
|
// first we check if the username match the presenters username
|
||||||
if (config.presenters && config.presenters.list && config.presenters.list.includes(peer_name)) {
|
if (config.presenters && config.presenters.list && config.presenters.list.includes(peer_name)) {
|
||||||
@@ -1062,7 +1113,9 @@ function startServer() {
|
|||||||
|
|
||||||
log.info('[Join] - Connected presenters grp by roomId', presenters);
|
log.info('[Join] - Connected presenters grp by roomId', presenters);
|
||||||
|
|
||||||
const isPresenter = await isPeerPresenter(socket.room_id, socket.id, peer_name, peer_uuid);
|
const isPresenter = peer_token
|
||||||
|
? is_presenter
|
||||||
|
: await isPeerPresenter(socket.room_id, socket.id, peer_name, peer_uuid);
|
||||||
|
|
||||||
room.getPeers().get(socket.id).updatePeerInfo({ type: 'presenter', status: isPresenter });
|
room.getPeers().get(socket.id).updatePeerInfo({ type: 'presenter', status: isPresenter });
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const { v4: uuidV4 } = require('uuid');
|
const { v4: uuidV4 } = require('uuid');
|
||||||
|
|
||||||
|
const JWT_KEY = (config.jwt && config.jwt.key) || 'mirotalksfu_jwt_secret';
|
||||||
|
const JWT_EXP = (config.jwt && config.jwt.exp) || '1h';
|
||||||
|
|
||||||
module.exports = class ServerApi {
|
module.exports = class ServerApi {
|
||||||
constructor(host = null, authorization = null) {
|
constructor(host = null, authorization = null) {
|
||||||
this._host = host;
|
this._host = host;
|
||||||
@@ -20,23 +24,37 @@ module.exports = class ServerApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getJoinURL(data) {
|
getJoinURL(data) {
|
||||||
|
// Get data...
|
||||||
|
const { room, roomPassword, name, audio, video, screen, notify, token } = data;
|
||||||
|
|
||||||
|
let jwtToken = '';
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
const { username, password, presenter, expire } = token;
|
||||||
|
jwtToken =
|
||||||
|
'&token=' +
|
||||||
|
jwt.sign({ username: username, password: password, presenter: presenter }, JWT_KEY, {
|
||||||
|
expiresIn: expire ? expire : JWT_EXP,
|
||||||
|
});
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
'https://' +
|
'https://' +
|
||||||
this._host +
|
this._host +
|
||||||
'/join?room=' +
|
'/join?room=' +
|
||||||
data.room +
|
room +
|
||||||
'&roomPassword=' +
|
'&roomPassword=' +
|
||||||
data.roomPassword +
|
roomPassword +
|
||||||
'&name=' +
|
'&name=' +
|
||||||
data.name +
|
name +
|
||||||
'&audio=' +
|
'&audio=' +
|
||||||
data.audio +
|
audio +
|
||||||
'&video=' +
|
'&video=' +
|
||||||
data.video +
|
video +
|
||||||
'&screen=' +
|
'&screen=' +
|
||||||
data.screen +
|
screen +
|
||||||
'¬ify=' +
|
'¬ify=' +
|
||||||
data.notify
|
notify +
|
||||||
|
jwtToken
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ module.exports = {
|
|||||||
//...
|
//...
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
jwt: {
|
||||||
|
/*
|
||||||
|
JWT https://jwt.io/
|
||||||
|
Securely manages credentials for host configurations and user authentication, enhancing security and streamlining processes.
|
||||||
|
*/
|
||||||
|
key: 'mirotalksfu_jwt_secret',
|
||||||
|
exp: '1h',
|
||||||
|
},
|
||||||
presenters: {
|
presenters: {
|
||||||
list: [
|
list: [
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mirotalksfu",
|
"name": "mirotalksfu",
|
||||||
"version": "1.3.65",
|
"version": "1.3.66",
|
||||||
"description": "WebRTC SFU browser-based video calls",
|
"description": "WebRTC SFU browser-based video calls",
|
||||||
"main": "Server.js",
|
"main": "Server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -48,10 +48,11 @@
|
|||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"express": "4.18.2",
|
"express": "4.18.2",
|
||||||
"httpolyglot": "0.1.2",
|
"httpolyglot": "0.1.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"mediasoup": "3.13.18",
|
"mediasoup": "3.13.18",
|
||||||
"mediasoup-client": "3.7.2",
|
"mediasoup-client": "3.7.2",
|
||||||
"ngrok": "^4.3.3",
|
"ngrok": "^4.3.3",
|
||||||
"openai": "^4.26.1",
|
"openai": "^4.27.0",
|
||||||
"qs": "6.11.2",
|
"qs": "6.11.2",
|
||||||
"socket.io": "4.7.4",
|
"socket.io": "4.7.4",
|
||||||
"swagger-ui-express": "5.0.0",
|
"swagger-ui-express": "5.0.0",
|
||||||
|
|||||||
@@ -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.3.65
|
* @version 1.3.66
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -175,8 +175,7 @@ let room_id = getRoomId();
|
|||||||
let room_password = getRoomPassword();
|
let room_password = getRoomPassword();
|
||||||
let peer_name = getPeerName();
|
let peer_name = getPeerName();
|
||||||
let peer_uuid = getPeerUUID();
|
let peer_uuid = getPeerUUID();
|
||||||
let peer_username = getPeerUsername();
|
let peer_token = getPeerToken();
|
||||||
let peer_password = getPeerPassword();
|
|
||||||
let isScreenAllowed = getScreen();
|
let isScreenAllowed = getScreen();
|
||||||
let isHideMeActive = getHideMeActive();
|
let isHideMeActive = getHideMeActive();
|
||||||
let notify = getNotify();
|
let notify = getNotify();
|
||||||
@@ -230,7 +229,7 @@ let initStream = null;
|
|||||||
|
|
||||||
let scriptProcessor = null;
|
let scriptProcessor = null;
|
||||||
|
|
||||||
const RoomURL = window.location.origin + '/join/' + room_id;
|
const RoomURL = window.location.origin + '/join/' + room_id; // window.location.origin + '/join/?room=' + roomId + '&token=' + myToken
|
||||||
|
|
||||||
let transcription;
|
let transcription;
|
||||||
|
|
||||||
@@ -690,28 +689,16 @@ function getPeerUUID() {
|
|||||||
return peer_uuid;
|
return peer_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPeerUsername() {
|
function getPeerToken() {
|
||||||
if (window.sessionStorage.peer_username) return window.sessionStorage.peer_username;
|
if (window.sessionStorage.peer_token) return window.sessionStorage.peer_token;
|
||||||
let qs = new URLSearchParams(window.location.search);
|
let qs = new URLSearchParams(window.location.search);
|
||||||
let username = filterXSS(qs.get('username'));
|
let token = filterXSS(qs.get('token'));
|
||||||
let queryUsername = false;
|
let queryToken = false;
|
||||||
if (username) {
|
if (token) {
|
||||||
queryUsername = username;
|
queryToken = token;
|
||||||
}
|
}
|
||||||
console.log('Direct join', { username: queryUsername });
|
console.log('Direct join', { token: queryToken });
|
||||||
return queryUsername;
|
return queryToken;
|
||||||
}
|
|
||||||
|
|
||||||
function getPeerPassword() {
|
|
||||||
if (window.sessionStorage.peer_password) return window.sessionStorage.peer_password;
|
|
||||||
let qs = new URLSearchParams(window.location.search);
|
|
||||||
let password = filterXSS(qs.get('password'));
|
|
||||||
let queryPassword = false;
|
|
||||||
if (password) {
|
|
||||||
queryPassword = password;
|
|
||||||
}
|
|
||||||
console.log('Direct join', { password: queryPassword });
|
|
||||||
return queryPassword;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRoomPassword() {
|
function getRoomPassword() {
|
||||||
@@ -755,8 +742,7 @@ function getPeerInfo() {
|
|||||||
peer_uuid: peer_uuid,
|
peer_uuid: peer_uuid,
|
||||||
peer_id: socket.id,
|
peer_id: socket.id,
|
||||||
peer_name: peer_name,
|
peer_name: peer_name,
|
||||||
peer_username: peer_username,
|
peer_token: peer_token,
|
||||||
peer_password: peer_password,
|
|
||||||
peer_presenter: isPresenter,
|
peer_presenter: isPresenter,
|
||||||
peer_audio: isAudioAllowed,
|
peer_audio: isAudioAllowed,
|
||||||
peer_video: isVideoAllowed,
|
peer_video: isVideoAllowed,
|
||||||
|
|||||||
@@ -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.3.65
|
* @version 1.3.66
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -374,11 +374,14 @@ class RoomClient {
|
|||||||
return this.isBanned();
|
return this.isBanned();
|
||||||
}
|
}
|
||||||
const peers = new Map(JSON.parse(room.peers));
|
const peers = new Map(JSON.parse(room.peers));
|
||||||
for (let peer of Array.from(peers.keys()).filter((id) => id !== this.peer_id)) {
|
if (!peer_info.peer_token) {
|
||||||
let peer_info = peers.get(peer).peer_info;
|
// hack...
|
||||||
if (peer_info.peer_name == this.peer_name) {
|
for (let peer of Array.from(peers.keys()).filter((id) => id !== this.peer_id)) {
|
||||||
console.log('00-WARNING ----> Username already in use');
|
let peer_info = peers.get(peer).peer_info;
|
||||||
return this.userNameAlreadyInRoom();
|
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);
|
||||||
@@ -909,7 +912,10 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getReconnectDirectJoinURL() {
|
getReconnectDirectJoinURL() {
|
||||||
return `${window.location.origin}/join?room=${this.room_id}&password=${this.RoomPassword}&name=${this.peer_name}&audio=${this.peer_info.peer_audio}&video=${this.peer_info.peer_video}&screen=${this.peer_info.peer_screen}¬ify=0&isPresenter=${isPresenter}`;
|
return (
|
||||||
|
`${window.location.origin}/join?room=${this.room_id}&password=${this.RoomPassword}&name=${this.peer_name}&audio=${this.peer_info.peer_audio}&video=${this.peer_info.peer_video}&screen=${this.peer_info.peer_screen}¬ify=0&isPresenter=${isPresenter}` +
|
||||||
|
(this.peer_info.peer_token ? `&token=${peer_info.peer_token}` : '')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|||||||
@@ -164,16 +164,21 @@
|
|||||||
console.log(response);
|
console.log(response);
|
||||||
|
|
||||||
// Store in session
|
// Store in session
|
||||||
window.sessionStorage.peer_username = username;
|
const token = response.data.message;
|
||||||
window.sessionStorage.peer_password = password;
|
window.sessionStorage.peer_token = token;
|
||||||
|
|
||||||
if (room) {
|
if (room) {
|
||||||
return (window.location.href =
|
return (window.location.href =
|
||||||
'/join/' + window.location.search);
|
'/join/' + window.location.search);
|
||||||
|
/*
|
||||||
|
return (window.location.href =
|
||||||
|
'/join/?room=' + room + '&token=' + token); */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roomPath) {
|
if (roomPath) {
|
||||||
return (window.location.href = '/join/' + roomPath);
|
return (window.location.href = '/join/' + roomPath);
|
||||||
|
/*
|
||||||
|
return (window.location.href =
|
||||||
|
'/join/?room=' + roomPath + '&token=' + token); */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (window.location.href = '/logged');
|
return (window.location.href = '/logged');
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم