Merge remote-tracking branch 'upstream/develop' into mm-exporter
This commit is contained in:
@@ -36,14 +36,14 @@ module.exports =
|
||||
},
|
||||
*/
|
||||
// URI and key for requesting geoip-based TURN server closest to the client
|
||||
turnAPIKey : 'examplekey',
|
||||
turnAPIURI : 'https://example.com/api/turn',
|
||||
turnAPIparams : {
|
||||
'uri_schema' : 'turn',
|
||||
'transport' : 'tcp',
|
||||
'ip_ver' : 'ipv4',
|
||||
'servercount' : '2'
|
||||
},
|
||||
turnAPIKey : 'examplekey',
|
||||
turnAPIURI : 'https://example.com/api/turn',
|
||||
turnAPIparams : {
|
||||
'uri_schema' : 'turn',
|
||||
'transport' : 'tcp',
|
||||
'ip_ver' : 'ipv4',
|
||||
'servercount' : '2'
|
||||
},
|
||||
|
||||
// Backup turnservers if REST fails or is not configured
|
||||
backupTurnServers : [
|
||||
@@ -60,23 +60,31 @@ module.exports =
|
||||
// session cookie secret
|
||||
cookieSecret : 'T0P-S3cR3t_cook!e',
|
||||
cookieName : 'multiparty-meeting.sid',
|
||||
// if you use encrypted private key the set the passphrase
|
||||
tls :
|
||||
{
|
||||
cert : `${__dirname}/../certs/mediasoup-demo.localhost.cert.pem`,
|
||||
// passphrase: 'key_password'
|
||||
key : `${__dirname}/../certs/mediasoup-demo.localhost.key.pem`
|
||||
},
|
||||
// listening Host or IP
|
||||
// If omitted listens on every IP. ("0.0.0.0" and "::")
|
||||
//listeningHost: 'localhost',
|
||||
// listeningHost: 'localhost',
|
||||
// Listening port for https server.
|
||||
listeningPort : 443,
|
||||
// Any http request is redirected to https.
|
||||
// Listening port for http server.
|
||||
// Listening port for http server.
|
||||
listeningRedirectPort : 80,
|
||||
// Listens only on http, only on listeningPort
|
||||
// listeningRedirectPort disabled
|
||||
// use case: loadbalancer backend
|
||||
httpOnly : false,
|
||||
// WebServer/Express trust proxy config for httpOnly mode
|
||||
// You can find more info:
|
||||
// - https://expressjs.com/en/guide/behind-proxies.html
|
||||
// - https://www.npmjs.com/package/proxy-addr
|
||||
// use case: loadbalancer backend
|
||||
trustProxy : '',
|
||||
// This logger class will have the log function
|
||||
// called every time there is a room created or destroyed,
|
||||
// or peer created or destroyed. This would then be able
|
||||
@@ -109,12 +117,6 @@ module.exports =
|
||||
});
|
||||
}
|
||||
}, */
|
||||
// WebServer/Express trust proxy config for httpOnly mode
|
||||
// You can find more info:
|
||||
// - https://expressjs.com/en/guide/behind-proxies.html
|
||||
// - https://www.npmjs.com/package/proxy-addr
|
||||
// use case: loadbalancer backend
|
||||
trustProxy : '',
|
||||
// This function will be called on successful login through oidc.
|
||||
// Use this function to map your oidc userinfo to the Peer object.
|
||||
// The roomId is equal to the room name.
|
||||
@@ -211,7 +213,7 @@ module.exports =
|
||||
//
|
||||
// Example:
|
||||
// [ userRoles.MODERATOR, userRoles.AUTHENTICATED ]
|
||||
accessFromRoles : {
|
||||
accessFromRoles : {
|
||||
// The role(s) will gain access to the room
|
||||
// even if it is locked (!)
|
||||
BYPASS_ROOM_LOCK : [ userRoles.ADMIN ],
|
||||
@@ -222,7 +224,7 @@ module.exports =
|
||||
// function, and change to BYPASS_LOBBY : [ userRoles.AUTHENTICATED ]
|
||||
BYPASS_LOBBY : [ userRoles.NORMAL ]
|
||||
},
|
||||
permissionsFromRoles : {
|
||||
permissionsFromRoles : {
|
||||
// The role(s) have permission to lock/unlock a room
|
||||
CHANGE_ROOM_LOCK : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to promote a peer from the lobby
|
||||
@@ -242,9 +244,9 @@ module.exports =
|
||||
},
|
||||
// When truthy, the room will be open to all users when as long as there
|
||||
// are allready users in the room
|
||||
activateOnHostJoin : true,
|
||||
activateOnHostJoin : true,
|
||||
// Mediasoup settings
|
||||
mediasoup :
|
||||
mediasoup :
|
||||
{
|
||||
numWorkers : Object.keys(os.cpus()).length,
|
||||
// mediasoup Worker settings.
|
||||
@@ -325,11 +327,12 @@ module.exports =
|
||||
{
|
||||
listenIps :
|
||||
[
|
||||
// change ip to your servers IP address!
|
||||
{ ip: '0.0.0.0', announcedIp: null }
|
||||
// change 192.0.2.1 IPv4 to your server's IPv4 address!!
|
||||
{ ip: '192.0.2.1', announcedIp: null }
|
||||
|
||||
// Can have multiple listening interfaces
|
||||
// { ip: '::/0', announcedIp: null }
|
||||
// change 2001:DB8::1 IPv6 to your server's IPv6 address!!
|
||||
// { ip: '2001:DB8::1', announcedIp: null }
|
||||
],
|
||||
initialAvailableOutgoingBitrate : 1000000,
|
||||
minimumAvailableOutgoingBitrate : 600000,
|
||||
|
||||
+103
-26
@@ -9,6 +9,27 @@ const config = require('../config/config');
|
||||
|
||||
const logger = new Logger('Room');
|
||||
|
||||
// In case they are not configured properly
|
||||
const accessFromRoles =
|
||||
{
|
||||
BYPASS_ROOM_LOCK : [ userRoles.ADMIN ],
|
||||
BYPASS_LOBBY : [ userRoles.NORMAL ],
|
||||
...config.accessFromRoles
|
||||
};
|
||||
|
||||
const permissionsFromRoles =
|
||||
{
|
||||
CHANGE_ROOM_LOCK : [ userRoles.NORMAL ],
|
||||
PROMOTE_PEER : [ userRoles.NORMAL ],
|
||||
SEND_CHAT : [ userRoles.NORMAL ],
|
||||
MODERATE_CHAT : [ userRoles.MODERATOR ],
|
||||
SHARE_SCREEN : [ userRoles.NORMAL ],
|
||||
SHARE_FILE : [ userRoles.NORMAL ],
|
||||
MODERATE_FILES : [ userRoles.MODERATOR ],
|
||||
MODERATE_ROOM : [ userRoles.MODERATOR ],
|
||||
...config.permissionsFromRoles
|
||||
};
|
||||
|
||||
class Room extends EventEmitter
|
||||
{
|
||||
/**
|
||||
@@ -152,7 +173,7 @@ class Room extends EventEmitter
|
||||
if (returning)
|
||||
this._peerJoining(peer, true);
|
||||
else if ( // Has a role that is allowed to bypass room lock
|
||||
peer.roles.some((role) => config.accessFromRoles.BYPASS_ROOM_LOCK.includes(role))
|
||||
peer.roles.some((role) => accessFromRoles.BYPASS_ROOM_LOCK.includes(role))
|
||||
)
|
||||
this._peerJoining(peer);
|
||||
else if (this._locked)
|
||||
@@ -160,7 +181,7 @@ class Room extends EventEmitter
|
||||
else
|
||||
{
|
||||
// Has a role that is allowed to bypass lobby
|
||||
peer.roles.some((role) => config.accessFromRoles.BYPASS_LOBBY.includes(role)) ?
|
||||
peer.roles.some((role) => accessFromRoles.BYPASS_LOBBY.includes(role)) ?
|
||||
this._peerJoining(peer) :
|
||||
this._handleGuest(peer);
|
||||
}
|
||||
@@ -187,7 +208,11 @@ class Room extends EventEmitter
|
||||
|
||||
this._peerJoining(promotedPeer);
|
||||
|
||||
for (const peer of this._getJoinedPeers())
|
||||
for (
|
||||
const peer of this._getPeersWithPermission({
|
||||
permission : permissionsFromRoles.PROMOTE_PEER
|
||||
})
|
||||
)
|
||||
{
|
||||
this._notification(peer.socket, 'lobby:promotedPeer', { peerId: id });
|
||||
}
|
||||
@@ -196,7 +221,7 @@ class Room extends EventEmitter
|
||||
this._lobby.on('peerRolesChanged', (peer) =>
|
||||
{
|
||||
if ( // Has a role that is allowed to bypass room lock
|
||||
peer.roles.some((role) => config.accessFromRoles.BYPASS_ROOM_LOCK.includes(role))
|
||||
peer.roles.some((role) => accessFromRoles.BYPASS_ROOM_LOCK.includes(role))
|
||||
)
|
||||
{
|
||||
this._lobby.promotePeer(peer.id);
|
||||
@@ -206,7 +231,7 @@ class Room extends EventEmitter
|
||||
|
||||
if ( // Has a role that is allowed to bypass lobby
|
||||
!this._locked &&
|
||||
peer.roles.some((role) => config.accessFromRoles.BYPASS_LOBBY.includes(role))
|
||||
peer.roles.some((role) => accessFromRoles.BYPASS_LOBBY.includes(role))
|
||||
)
|
||||
{
|
||||
this._lobby.promotePeer(peer.id);
|
||||
@@ -219,7 +244,11 @@ class Room extends EventEmitter
|
||||
{
|
||||
const { id, displayName } = changedPeer;
|
||||
|
||||
for (const peer of this._getJoinedPeers())
|
||||
for (
|
||||
const peer of this._getPeersWithPermission({
|
||||
permission : permissionsFromRoles.PROMOTE_PEER
|
||||
})
|
||||
)
|
||||
{
|
||||
this._notification(peer.socket, 'lobby:changeDisplayName', { peerId: id, displayName });
|
||||
}
|
||||
@@ -229,7 +258,11 @@ class Room extends EventEmitter
|
||||
{
|
||||
const { id, picture } = changedPeer;
|
||||
|
||||
for (const peer of this._getJoinedPeers())
|
||||
for (
|
||||
const peer of this._getPeersWithPermission({
|
||||
permission : permissionsFromRoles.PROMOTE_PEER
|
||||
})
|
||||
)
|
||||
{
|
||||
this._notification(peer.socket, 'lobby:changePicture', { peerId: id, picture });
|
||||
}
|
||||
@@ -241,7 +274,11 @@ class Room extends EventEmitter
|
||||
|
||||
const { id } = closedPeer;
|
||||
|
||||
for (const peer of this._getJoinedPeers())
|
||||
for (
|
||||
const peer of this._getPeersWithPermission({
|
||||
permission : permissionsFromRoles.PROMOTE_PEER
|
||||
})
|
||||
)
|
||||
{
|
||||
this._notification(peer.socket, 'lobby:peerClosed', { peerId: id });
|
||||
}
|
||||
@@ -344,7 +381,11 @@ class Room extends EventEmitter
|
||||
{
|
||||
this._lobby.parkPeer(parkPeer);
|
||||
|
||||
for (const peer of this._getJoinedPeers())
|
||||
for (
|
||||
const peer of this._getPeersWithPermission({
|
||||
permission : permissionsFromRoles.PROMOTE_PEER
|
||||
})
|
||||
)
|
||||
{
|
||||
this._notification(peer.socket, 'parkedPeer', { peerId: parkPeer.id });
|
||||
}
|
||||
@@ -384,8 +425,8 @@ class Room extends EventEmitter
|
||||
{
|
||||
params : {
|
||||
...config.turnAPIparams,
|
||||
'api_key' : config.turnAPIKey,
|
||||
'ip' : peer.socket.request.connection.remoteAddress
|
||||
'api_key' : config.turnAPIKey,
|
||||
'ip' : peer.socket.request.connection.remoteAddress
|
||||
}
|
||||
});
|
||||
|
||||
@@ -550,7 +591,7 @@ class Room extends EventEmitter
|
||||
peers : peerInfos,
|
||||
tracker : config.fileTracker,
|
||||
authenticated : peer.authenticated,
|
||||
permissionsFromRoles : config.permissionsFromRoles,
|
||||
permissionsFromRoles : permissionsFromRoles,
|
||||
userRoles : userRoles
|
||||
});
|
||||
|
||||
@@ -682,9 +723,10 @@ class Room extends EventEmitter
|
||||
|
||||
if (
|
||||
appData.source === 'screen' &&
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.SHARE_SCREEN.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.SHARE_SCREEN.includes(role))
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
// Ensure the Peer is joined.
|
||||
if (!peer.joined)
|
||||
@@ -985,7 +1027,7 @@ class Room extends EventEmitter
|
||||
case 'chatMessage':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.SEND_CHAT.includes(role))
|
||||
!peer.roles.some((role) => permissionsFromRoles.SEND_CHAT.includes(role))
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1008,7 +1050,9 @@ class Room extends EventEmitter
|
||||
case 'moderator:clearChat':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_CHAT.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.MODERATE_CHAT.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1046,7 +1090,9 @@ class Room extends EventEmitter
|
||||
case 'lockRoom':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1066,7 +1112,9 @@ class Room extends EventEmitter
|
||||
case 'unlockRoom':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1126,7 +1174,9 @@ class Room extends EventEmitter
|
||||
case 'promotePeer':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.PROMOTE_PEER.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.PROMOTE_PEER.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1143,7 +1193,9 @@ class Room extends EventEmitter
|
||||
case 'promoteAllPeers':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.PROMOTE_PEER.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.PROMOTE_PEER.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1158,7 +1210,9 @@ class Room extends EventEmitter
|
||||
case 'sendFile':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.SHARE_FILE.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.SHARE_FILE.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1181,7 +1235,9 @@ class Room extends EventEmitter
|
||||
case 'moderator:clearFileSharing':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_FILES.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.MODERATE_FILES.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1217,7 +1273,9 @@ class Room extends EventEmitter
|
||||
case 'moderator:muteAll':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1232,7 +1290,9 @@ class Room extends EventEmitter
|
||||
case 'moderator:stopAllVideo':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1247,7 +1307,9 @@ class Room extends EventEmitter
|
||||
case 'moderator:closeMeeting':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1264,7 +1326,9 @@ class Room extends EventEmitter
|
||||
case 'moderator:kickPeer':
|
||||
{
|
||||
if (
|
||||
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
|
||||
!peer.roles.some(
|
||||
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
|
||||
)
|
||||
)
|
||||
throw new Error('peer not authorized');
|
||||
|
||||
@@ -1452,6 +1516,19 @@ class Room extends EventEmitter
|
||||
.filter((peer) => peer.joined && peer !== excludePeer);
|
||||
}
|
||||
|
||||
_getPeersWithPermission({ permission = null, excludePeer = undefined, joined = true })
|
||||
{
|
||||
return Object.values(this._peers)
|
||||
.filter(
|
||||
(peer) =>
|
||||
peer.joined === joined &&
|
||||
peer !== excludePeer &&
|
||||
peer.roles.some(
|
||||
(role) => permission.includes(role)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_timeoutCallback(callback)
|
||||
{
|
||||
let called = false;
|
||||
|
||||
+5
-1
@@ -8,7 +8,8 @@
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"start": "DEBUG=${DEBUG:='*mediasoup* *INFO* *WARN* *ERROR*'} INTERACTIVE=${INTERACTIVE:='true'} node server.js",
|
||||
"connect": "node connect.js"
|
||||
"connect": "node connect.js",
|
||||
"lint": "eslint -c .eslintrc.json --ext .js *.js lib/"
|
||||
},
|
||||
"dependencies": {
|
||||
"awaitqueue": "^1.0.0",
|
||||
@@ -36,5 +37,8 @@
|
||||
"socket.io": "^2.3.0",
|
||||
"spdy": "^4.0.1",
|
||||
"uuid": "^7.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "6.8.0"
|
||||
}
|
||||
}
|
||||
|
||||
+18
-5
@@ -203,7 +203,7 @@ function setupLTI(ltiConfig)
|
||||
if (lti.user_id && lti.custom_room)
|
||||
{
|
||||
user.id = lti.user_id;
|
||||
user._userinfo = { "lti" : lti };
|
||||
user._userinfo = { 'lti': lti };
|
||||
}
|
||||
|
||||
if (lti.custom_room)
|
||||
@@ -244,7 +244,18 @@ function setupOIDC(oidcIssuer)
|
||||
// redirect_uri defaults to client.redirect_uris[0]
|
||||
// response type defaults to client.response_types[0], then 'code'
|
||||
// scope defaults to 'openid'
|
||||
const params = config.auth.oidc.clientOptions;
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
const params = (({
|
||||
client_id,
|
||||
redirect_uri,
|
||||
scope
|
||||
}) => ({
|
||||
client_id,
|
||||
redirect_uri,
|
||||
scope
|
||||
}))(config.auth.oidc.clientOptions);
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
// optional, defaults to false, when true req is passed as a first
|
||||
// argument to verify fn
|
||||
@@ -259,7 +270,9 @@ function setupOIDC(oidcIssuer)
|
||||
{ client: oidcClient, params, passReqToCallback, usePKCE },
|
||||
(tokenset, userinfo, done) =>
|
||||
{
|
||||
if (userinfo && tokenset) {
|
||||
if (userinfo && tokenset)
|
||||
{
|
||||
// eslint-disable-next-line camelcase
|
||||
userinfo._tokenset_claims = tokenset.claims();
|
||||
}
|
||||
|
||||
@@ -434,14 +447,14 @@ async function runHttpsServer()
|
||||
// http
|
||||
const redirectListener = http.createServer(app);
|
||||
|
||||
if(config.listeningHost)
|
||||
if (config.listeningHost)
|
||||
redirectListener.listen(config.listeningRedirectPort, config.listeningHost);
|
||||
else
|
||||
redirectListener.listen(config.listeningRedirectPort);
|
||||
}
|
||||
|
||||
// https or http
|
||||
if(config.listeningHost)
|
||||
if (config.listeningHost)
|
||||
mainListener.listen(config.listeningPort, config.listeningHost);
|
||||
else
|
||||
mainListener.listen(config.listeningPort);
|
||||
|
||||
+1
-1
@@ -7,5 +7,5 @@ module.exports = {
|
||||
// Don't change anything after this point
|
||||
|
||||
// All users have this role by default, do not change or remove this role
|
||||
NORMAL : 'normal'
|
||||
NORMAL : 'normal'
|
||||
};
|
||||
Reference in New Issue
Block a user