Merge branch 'feat-roles-authorization' into develop

This commit is contained in:
Håvar Aambø Fosstveit
2020-04-02 00:32:38 +02:00
16 changed files with 218 additions and 136 deletions
+28 -6
View File
@@ -194,15 +194,37 @@ module.exports =
peer.email = userinfo.email;
}
},
// Required roles for Access. All users have the role "ALL" by default.
// Other roles need to be added in the "userMapping" function. This
// is an Array of roles. userRoles.ADMIN have all priveleges and access
// always.
// All users have the role "NORMAL" by default. Other roles need to be
// added in the "userMapping" function. The following accesses and
// permissions are arrays of roles. Roles can be changed in userRoles.js
//
// Example:
// [ userRoles.MODERATOR, userRoles.AUTHENTICATED ]
// This will allow all MODERATOR and AUTHENTICATED users access.
requiredRolesForAccess : [ userRoles.ALL ],
accessFromRoles : {
// The role(s) will gain access to the room
// even if it is locked (!)
BYPASS_ROOM_LOCK : [ userRoles.ADMIN ],
// The role(s) will gain access to the room without
// going into the lobby. If you want to restrict access to your
// server to only directly allow authenticated users, you could
// add the userRoles.AUTHENTICATED to the user in the userMapping
// function, and change to BYPASS_LOBBY : [ userRoles.AUTHENTICATED ]
BYPASS_LOBBY : [ userRoles.NORMAL ]
},
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
PROMOTE_PEER : [ userRoles.NORMAL ],
// The role(s) have permission to send chat messages
SEND_CHAT : [ userRoles.NORMAL ],
// The role(s) have permission to share screen
SHARE_SCREEN : [ userRoles.NORMAL ],
// The role(s) have permission to share files
SHARE_FILE : [ userRoles.NORMAL ],
// The role(s) have permission to moderate room (e.g. kick user)
MODERATE_ROOM : [ userRoles.MODERATOR ]
},
// When truthy, the room will be open to all users when as long as there
// are allready users in the room
activateOnHostJoin : true,
+1 -1
View File
@@ -27,7 +27,7 @@ class Peer extends EventEmitter
this._authenticated = false;
this._roles = [ userRoles.ALL ];
this._roles = [ userRoles.NORMAL ];
this._displayName = false;
+61 -31
View File
@@ -59,12 +59,6 @@ class Room extends EventEmitter
// Locked flag.
this._locked = false;
// Required roles to access
this._requiredRoles = [ userRoles.ALL ];
if ('requiredRolesForAccess' in config)
this._requiredRoles = config.requiredRolesForAccess;
// if true: accessCode is a possibility to open the room
this._joinByAccesCode = true;
@@ -157,15 +151,16 @@ class Room extends EventEmitter
// Returning user
if (returning)
this._peerJoining(peer, true);
// Always let ADMIN in, even if locked
else if (peer.roles.includes(userRoles.ADMIN))
else if ( // Has a role that is allowed to bypass room lock
peer.roles.some((role) => config.accessFromRoles.BYPASS_ROOM_LOCK.includes(role))
)
this._peerJoining(peer);
else if (this._locked)
this._parkPeer(peer);
else
{
// If the user has a role in config.requiredRolesForAccess, let them in
peer.roles.some((role) => this._requiredRoles.includes(role)) ?
// Has a role that is allowed to bypass lobby
peer.roles.some((role) => config.accessFromRoles.BYPASS_LOBBY.includes(role)) ?
this._peerJoining(peer) :
this._handleGuest(peer);
}
@@ -200,18 +195,18 @@ class Room extends EventEmitter
this._lobby.on('peerRolesChanged', (peer) =>
{
// Always let admin in, even if locked
if (peer.roles.includes(userRoles.ADMIN))
if ( // Has a role that is allowed to bypass room lock
peer.roles.some((role) => config.accessFromRoles.BYPASS_ROOM_LOCK.includes(role))
)
{
this._lobby.promotePeer(peer.id);
return;
}
// If the user has a role in config.requiredRolesForAccess, let them in
if (
if ( // Has a role that is allowed to bypass lobby
!this._locked &&
peer.roles.some((role) => this._requiredRoles.includes(role))
peer.roles.some((role) => config.accessFromRoles.BYPASS_LOBBY.includes(role))
)
{
this._lobby.promotePeer(peer.id);
@@ -554,9 +549,11 @@ class Room extends EventEmitter
.map((joinedPeer) => (joinedPeer.peerInfo));
cb(null, {
roles : peer.roles,
peers : peerInfos,
authenticated : peer.authenticated
roles : peer.roles,
peers : peerInfos,
authenticated : peer.authenticated,
permissionsFromRoles : config.permissionsFromRoles,
userRoles : userRoles
});
// Mark the new Peer as joined.
@@ -683,12 +680,19 @@ class Room extends EventEmitter
case 'produce':
{
let { appData } = request.data;
if (
appData.source === 'screen' &&
!peer.roles.some((role) => config.permissionsFromRoles.SHARE_SCREEN.includes(role))
)
throw new Error('peer not authorized');
// Ensure the Peer is joined.
if (!peer.joined)
throw new Error('Peer not yet joined');
const { transportId, kind, rtpParameters } = request.data;
let { appData } = request.data;
const transport = peer.getTransport(transportId);
if (!transport)
@@ -982,6 +986,11 @@ class Room extends EventEmitter
case 'chatMessage':
{
if (
!peer.roles.some((role) => config.permissionsFromRoles.SEND_CHAT.includes(role))
)
throw new Error('peer not authorized');
const { chatMessage } = request.data;
this._chatHistory.push(chatMessage);
@@ -1020,6 +1029,11 @@ class Room extends EventEmitter
case 'lockRoom':
{
if (
!peer.roles.some((role) => config.permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role))
)
throw new Error('peer not authorized');
this._locked = true;
// Spread to others
@@ -1035,6 +1049,11 @@ class Room extends EventEmitter
case 'unlockRoom':
{
if (
!peer.roles.some((role) => config.permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role))
)
throw new Error('peer not authorized');
this._locked = false;
// Spread to others
@@ -1090,6 +1109,11 @@ class Room extends EventEmitter
case 'promotePeer':
{
if (
!peer.roles.some((role) => config.permissionsFromRoles.PROMOTE_PEER.includes(role))
)
throw new Error('peer not authorized');
const { peerId } = request.data;
this._lobby.promotePeer(peerId);
@@ -1102,6 +1126,11 @@ class Room extends EventEmitter
case 'promoteAllPeers':
{
if (
!peer.roles.some((role) => config.permissionsFromRoles.PROMOTE_PEER.includes(role))
)
throw new Error('peer not authorized');
this._lobby.promoteAllPeers();
// Return no error
@@ -1112,6 +1141,11 @@ class Room extends EventEmitter
case 'sendFile':
{
if (
!peer.roles.some((role) => config.permissionsFromRoles.SHARE_FILE.includes(role))
)
throw new Error('peer not authorized');
const { magnetUri } = request.data;
this._fileHistory.push({ peerId: peer.id, magnetUri: magnetUri });
@@ -1149,10 +1183,9 @@ class Room extends EventEmitter
case 'moderator:muteAll':
{
if (
!peer.hasRole(userRoles.MODERATOR) &&
!peer.hasRole(userRoles.ADMIN)
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
)
throw new Error('peer does not have moderator priveleges');
throw new Error('peer not authorized');
// Spread to others
this._notification(peer.socket, 'moderator:mute', {
@@ -1167,10 +1200,9 @@ class Room extends EventEmitter
case 'moderator:stopAllVideo':
{
if (
!peer.hasRole(userRoles.MODERATOR) &&
!peer.hasRole(userRoles.ADMIN)
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
)
throw new Error('peer does not have moderator priveleges');
throw new Error('peer not authorized');
// Spread to others
this._notification(peer.socket, 'moderator:stopVideo', {
@@ -1185,10 +1217,9 @@ class Room extends EventEmitter
case 'moderator:closeMeeting':
{
if (
!peer.hasRole(userRoles.MODERATOR) &&
!peer.hasRole(userRoles.ADMIN)
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
)
throw new Error('peer does not have moderator priveleges');
throw new Error('peer not authorized');
this._notification(
peer.socket,
@@ -1208,10 +1239,9 @@ class Room extends EventEmitter
case 'moderator:kickPeer':
{
if (
!peer.hasRole(userRoles.MODERATOR) &&
!peer.hasRole(userRoles.ADMIN)
!peer.roles.some((role) => config.permissionsFromRoles.MODERATE_ROOM.includes(role))
)
throw new Error('peer does not have moderator priveleges');
throw new Error('peer not authorized');
const { peerId } = request.data;
+1 -1
View File
@@ -327,7 +327,7 @@ async function setupAuth()
{
for (const role of peer.roles)
{
if (role !== userRoles.ALL)
if (role !== userRoles.NORMAL)
peer.removeRole(role);
}
}
+6 -7
View File
@@ -1,12 +1,11 @@
module.exports = {
// Allowed to enter locked rooms + all other priveleges
// These can be changed
ADMIN : 'admin',
// Allowed to enter restricted rooms if configured.
// Allowed to moderate users in a room (mute all,
// spotlight video, kick users)
MODERATOR : 'moderator',
// Same as MODERATOR, but can't moderate users
PRESENTER : 'presenter',
AUTHENTICATED : 'authenticated',
// No priveleges
ALL : 'normal'
// Don't change anything after this point
// All users have this role by default, do not change or remove this role
NORMAL : 'normal'
};