diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js
index 1f42c0d..4f94d8c 100644
--- a/app/src/RoomClient.js
+++ b/app/src/RoomClient.js
@@ -2371,10 +2371,8 @@ export default class RoomClient
{
logger.debug('_joinRoom()');
- const {
- displayName,
- picture
- } = store.getState().settings;
+ const { displayName } = store.getState().settings;
+ const { picture } = store.getState().me;
try
{
@@ -2524,7 +2522,13 @@ export default class RoomClient
canShareFiles : this._torrentSupport
}));
- const { authenticated, roles, peers } = await this.sendRequest(
+ const {
+ authenticated,
+ roles,
+ peers,
+ permissionsFromRoles,
+ userRoles
+ } = await this.sendRequest(
'join',
{
displayName : displayName,
@@ -2541,6 +2545,9 @@ export default class RoomClient
store.dispatch(meActions.loggedIn(authenticated));
+ store.dispatch(roomActions.setUserRoles(userRoles));
+ store.dispatch(roomActions.setPermissionsFromRoles(permissionsFromRoles));
+
const myRoles = store.getState().me.roles;
for (const role of roles)
diff --git a/app/src/actions/roomActions.js b/app/src/actions/roomActions.js
index 6003b9e..1e93453 100644
--- a/app/src/actions/roomActions.js
+++ b/app/src/actions/roomActions.js
@@ -127,4 +127,16 @@ export const setCloseMeetingInProgress = (flag) =>
({
type : 'CLOSE_MEETING_IN_PROGRESS',
payload : { flag }
+ });
+
+export const setUserRoles = (userRoles) =>
+ ({
+ type : 'SET_USER_ROLES',
+ payload : { userRoles }
+ });
+
+export const setPermissionsFromRoles = (permissionsFromRoles) =>
+ ({
+ type : 'SET_PERMISSIONS_FROM_ROLES',
+ payload : { permissionsFromRoles }
});
\ No newline at end of file
diff --git a/app/src/components/AccessControl/LockDialog/ListLobbyPeer.js b/app/src/components/AccessControl/LockDialog/ListLobbyPeer.js
index 94d04d2..97f1ff6 100644
--- a/app/src/components/AccessControl/LockDialog/ListLobbyPeer.js
+++ b/app/src/components/AccessControl/LockDialog/ListLobbyPeer.js
@@ -7,72 +7,16 @@ import { withRoomContext } from '../../../RoomContext';
import { useIntl } from 'react-intl';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
-import ListItemIcon from '@material-ui/core/ListItemIcon';
+import IconButton from '@material-ui/core/IconButton';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
import Avatar from '@material-ui/core/Avatar';
import EmptyAvatar from '../../../images/avatar-empty.jpeg';
import PromoteIcon from '@material-ui/icons/OpenInBrowser';
import Tooltip from '@material-ui/core/Tooltip';
-const styles = (theme) =>
+const styles = () =>
({
root :
- {
- padding : theme.spacing(1),
- width : '100%',
- overflow : 'hidden',
- cursor : 'auto',
- display : 'flex'
- },
- avatar :
- {
- borderRadius : '50%',
- height : '2rem'
- },
- peerInfo :
- {
- fontSize : '1rem',
- border : 'none',
- display : 'flex',
- paddingLeft : theme.spacing(1),
- flexGrow : 1,
- alignItems : 'center'
- },
- controls :
- {
- float : 'right',
- display : 'flex',
- flexDirection : 'row',
- justifyContent : 'flex-start',
- alignItems : 'center'
- },
- button :
- {
- flex : '0 0 auto',
- margin : '0.3rem',
- borderRadius : 2,
- backgroundColor : 'rgba(0, 0, 0, 0.5)',
- cursor : 'pointer',
- transitionProperty : 'opacity, background-color',
- transitionDuration : '0.15s',
- width : 'var(--media-control-button-size)',
- height : 'var(--media-control-button-size)',
- opacity : 0.85,
- '&:hover' :
- {
- opacity : 1
- },
- '&.disabled' :
- {
- pointerEvents : 'none',
- backgroundColor : 'var(--media-control-botton-disabled)'
- },
- '&.promote' :
- {
- backgroundColor : 'var(--media-control-botton-on)'
- }
- },
- ListItem :
{
alignItems : 'center'
}
@@ -83,6 +27,7 @@ const ListLobbyPeer = (props) =>
const {
roomClient,
peer,
+ canPromote,
classes
} = props;
@@ -92,7 +37,7 @@ const ListLobbyPeer = (props) =>
return (
defaultMessage : 'Click to let them in'
})}
>
-
{
e.stopPropagation();
@@ -120,7 +63,7 @@ const ListLobbyPeer = (props) =>
}}
>
-
+
);
@@ -131,13 +74,17 @@ ListLobbyPeer.propTypes =
roomClient : PropTypes.any.isRequired,
advancedMode : PropTypes.bool,
peer : PropTypes.object.isRequired,
+ canPromote : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired
};
const mapStateToProps = (state, { id }) =>
{
return {
- peer : state.lobbyPeers[id]
+ peer : state.lobbyPeers[id],
+ canPromote :
+ state.me.roles.some((role) =>
+ state.room.permissionsFromRoles.PROMOTE_PEER.includes(role))
};
};
@@ -149,6 +96,8 @@ export default withRoomContext(connect(
areStatesEqual : (next, prev) =>
{
return (
+ prev.room.permissionsFromRoles === next.room.permissionsFromRoles &&
+ prev.me.roles === next.me.roles &&
prev.lobbyPeers === next.lobbyPeers
);
}
diff --git a/app/src/components/Containers/Me.js b/app/src/components/Containers/Me.js
index 3003f3d..09eb2d6 100644
--- a/app/src/components/Containers/Me.js
+++ b/app/src/components/Containers/Me.js
@@ -144,6 +144,7 @@ const Me = (props) =>
micProducer,
webcamProducer,
screenProducer,
+ canShareScreen,
classes,
theme
} = props;
@@ -396,7 +397,11 @@ const Me = (props) =>
defaultMessage : 'Start screen sharing'
})}
className={classes.fab}
- disabled={!me.canShareScreen || me.screenShareInProgress}
+ disabled={
+ !canShareScreen ||
+ !me.canShareScreen ||
+ me.screenShareInProgress
+ }
color={screenState === 'on' ? 'primary' : 'default'}
size={smallButtons ? 'small' : 'large'}
onClick={() =>
@@ -537,6 +542,7 @@ Me.propTypes =
spacing : PropTypes.number,
style : PropTypes.object,
smallButtons : PropTypes.bool,
+ canShareScreen : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired,
theme : PropTypes.object.isRequired
};
@@ -544,10 +550,13 @@ Me.propTypes =
const mapStateToProps = (state) =>
{
return {
- me : state.me,
+ me : state.me,
...meProducersSelector(state),
- settings : state.settings,
- activeSpeaker : state.me.id === state.room.activeSpeakerId
+ settings : state.settings,
+ activeSpeaker : state.me.id === state.room.activeSpeakerId,
+ canShareScreen :
+ state.me.roles.some((role) =>
+ state.room.permissionsFromRoles.SHARE_SCREEN.includes(role))
};
};
@@ -559,6 +568,7 @@ export default withRoomContext(connect(
areStatesEqual : (next, prev) =>
{
return (
+ prev.room.permissionsFromRoles === next.room.permissionsFromRoles &&
prev.me === next.me &&
prev.producers === next.producers &&
prev.settings === next.settings &&
diff --git a/app/src/components/Controls/TopBar.js b/app/src/components/Controls/TopBar.js
index 50a20c0..094af23 100644
--- a/app/src/components/Controls/TopBar.js
+++ b/app/src/components/Controls/TopBar.js
@@ -135,6 +135,7 @@ const TopBar = (props) =>
toggleToolArea,
openUsersTab,
unread,
+ canLock,
classes
} = props;
@@ -271,6 +272,7 @@ const TopBar = (props) =>
})}
className={classes.actionButton}
color='inherit'
+ disabled={!canLock}
onClick={() =>
{
if (room.locked)
@@ -377,6 +379,7 @@ TopBar.propTypes =
toggleToolArea : PropTypes.func.isRequired,
openUsersTab : PropTypes.func.isRequired,
unread : PropTypes.number.isRequired,
+ canLock : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired,
theme : PropTypes.object.isRequired
};
@@ -391,7 +394,10 @@ const mapStateToProps = (state) =>
loginEnabled : state.me.loginEnabled,
myPicture : state.me.picture,
unread : state.toolarea.unreadMessages +
- state.toolarea.unreadFiles
+ state.toolarea.unreadFiles,
+ canLock :
+ state.me.roles.some((role) =>
+ state.room.permissionsFromRoles.CHANGE_ROOM_LOCK.includes(role))
});
const mapDispatchToProps = (dispatch) =>
@@ -434,6 +440,7 @@ export default withRoomContext(connect(
prev.me.loggedIn === next.me.loggedIn &&
prev.me.loginEnabled === next.me.loginEnabled &&
prev.me.picture === next.me.picture &&
+ prev.me.roles === next.me.roles &&
prev.toolarea.unreadMessages === next.toolarea.unreadMessages &&
prev.toolarea.unreadFiles === next.toolarea.unreadFiles
);
diff --git a/app/src/components/MeetingDrawer/Chat/ChatInput.js b/app/src/components/MeetingDrawer/Chat/ChatInput.js
index 5be44e9..480bb26 100644
--- a/app/src/components/MeetingDrawer/Chat/ChatInput.js
+++ b/app/src/components/MeetingDrawer/Chat/ChatInput.js
@@ -54,6 +54,7 @@ const ChatInput = (props) =>
roomClient,
displayName,
picture,
+ canChat,
classes
} = props;
@@ -66,6 +67,7 @@ const ChatInput = (props) =>
defaultMessage : 'Enter chat message...'
})}
value={message || ''}
+ disabled={!canChat}
onChange={handleChange}
onKeyPress={(ev) =>
{
@@ -89,6 +91,7 @@ const ChatInput = (props) =>
color='primary'
className={classes.iconButton}
aria-label='Send'
+ disabled={!canChat}
onClick={() =>
{
if (message && message !== '')
@@ -112,13 +115,17 @@ ChatInput.propTypes =
roomClient : PropTypes.object.isRequired,
displayName : PropTypes.string,
picture : PropTypes.string,
+ canChat : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired
};
const mapStateToProps = (state) =>
({
displayName : state.settings.displayName,
- picture : state.me.picture
+ picture : state.me.picture,
+ canChat :
+ state.me.roles.some((role) =>
+ state.room.permissionsFromRoles.SEND_CHAT.includes(role))
});
export default withRoomContext(
@@ -130,6 +137,8 @@ export default withRoomContext(
areStatesEqual : (next, prev) =>
{
return (
+ prev.room.permissionsFromRoles === next.room.permissionsFromRoles &&
+ prev.me.roles === next.me.roles &&
prev.settings.displayName === next.settings.displayName &&
prev.me.picture === next.me.picture
);
diff --git a/app/src/components/MeetingDrawer/FileSharing/FileSharing.js b/app/src/components/MeetingDrawer/FileSharing/FileSharing.js
index 8713134..a3ff80e 100644
--- a/app/src/components/MeetingDrawer/FileSharing/FileSharing.js
+++ b/app/src/components/MeetingDrawer/FileSharing/FileSharing.js
@@ -41,6 +41,7 @@ const FileSharing = (props) =>
const {
canShareFiles,
+ canShare,
classes
} = props;
@@ -60,6 +61,7 @@ const FileSharing = (props) =>
@@ -68,7 +70,7 @@ const FileSharing = (props) =>
variant='contained'
component='span'
className={classes.button}
- disabled={!canShareFiles}
+ disabled={!canShareFiles || !canShare}
>
{buttonDescription}
@@ -83,6 +85,7 @@ FileSharing.propTypes = {
roomClient : PropTypes.any.isRequired,
canShareFiles : PropTypes.bool.isRequired,
tabOpen : PropTypes.bool.isRequired,
+ canShare : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired
};
@@ -90,10 +93,26 @@ const mapStateToProps = (state) =>
{
return {
canShareFiles : state.me.canShareFiles,
- tabOpen : state.toolarea.currentToolTab === 'files'
+ tabOpen : state.toolarea.currentToolTab === 'files',
+ canShare :
+ state.me.roles.some((role) =>
+ state.room.permissionsFromRoles.SHARE_FILE.includes(role))
};
};
export default withRoomContext(connect(
- mapStateToProps
+ mapStateToProps,
+ null,
+ null,
+ {
+ areStatesEqual : (next, prev) =>
+ {
+ return (
+ prev.room.permissionsFromRoles === next.room.permissionsFromRoles &&
+ prev.me.roles === next.me.roles &&
+ prev.me.canShareFiles === next.me.canShareFiles &&
+ prev.toolarea.currentToolTab === next.toolarea.currentToolTab
+ );
+ }
+ }
)(withStyles(styles)(FileSharing)));
diff --git a/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js b/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js
index 8f6453b..8847c06 100644
--- a/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js
+++ b/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js
@@ -13,7 +13,6 @@ import ListPeer from './ListPeer';
import ListMe from './ListMe';
import ListModerator from './ListModerator';
import Volume from '../../Containers/Volume';
-import * as userRoles from '../../../reducers/userRoles';
const styles = (theme) =>
({
@@ -174,8 +173,9 @@ ParticipantList.propTypes =
const mapStateToProps = (state) =>
{
return {
- isModerator : state.me.roles.includes(userRoles.MODERATOR) ||
- state.me.roles.includes(userRoles.ADMIN),
+ isModerator :
+ state.me.roles.some((role) =>
+ state.room.permissionsFromRoles.MODERATE_ROOM.includes(role)),
passivePeers : passivePeersSelector(state),
selectedPeerId : state.room.selectedPeerId,
spotlightPeers : spotlightSortedPeersSelector(state)
@@ -190,6 +190,7 @@ const ParticipantListContainer = withRoomContext(connect(
areStatesEqual : (next, prev) =>
{
return (
+ prev.room.permissionsFromRoles === next.room.permissionsFromRoles &&
prev.me.roles === next.me.roles &&
prev.peers === next.peers &&
prev.room.spotlights === next.room.spotlights &&
diff --git a/app/src/reducers/me.js b/app/src/reducers/me.js
index 70bfbfc..9ed18cd 100644
--- a/app/src/reducers/me.js
+++ b/app/src/reducers/me.js
@@ -1,11 +1,9 @@
-import * as userRoles from './userRoles';
-
const initialState =
{
id : null,
picture : null,
isMobile : false,
- roles : [ userRoles.ALL ],
+ roles : [ 'normal' ], // Default role
canSendMic : false,
canSendWebcam : false,
canShareScreen : false,
diff --git a/app/src/reducers/room.js b/app/src/reducers/room.js
index d963a0c..0f735d0 100644
--- a/app/src/reducers/room.js
+++ b/app/src/reducers/room.js
@@ -21,7 +21,16 @@ const initialState =
joined : false,
muteAllInProgress : false,
stopAllVideoInProgress : false,
- closeMeetingInProgress : false
+ closeMeetingInProgress : false,
+ userRoles : { NORMAL: 'normal' }, // Default role
+ permissionsFromRoles : {
+ CHANGE_ROOM_LOCK : [],
+ PROMOTE_PEER : [],
+ SEND_CHAT : [],
+ SHARE_SCREEN : [],
+ SHARE_FILE : [],
+ MODERATE_ROOM : []
+ }
};
const room = (state = initialState, action) =>
@@ -175,6 +184,20 @@ const room = (state = initialState, action) =>
case 'CLOSE_MEETING_IN_PROGRESS':
return { ...state, closeMeetingInProgress: action.payload.flag };
+ case 'SET_USER_ROLES':
+ {
+ const { userRoles } = action.payload;
+
+ return { ...state, userRoles };
+ }
+
+ case 'SET_PERMISSIONS_FROM_ROLES':
+ {
+ const { permissionsFromRoles } = action.payload;
+
+ return { ...state, permissionsFromRoles };
+ }
+
default:
return state;
}
diff --git a/app/src/reducers/userRoles.js b/app/src/reducers/userRoles.js
deleted file mode 100644
index 217a760..0000000
--- a/app/src/reducers/userRoles.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export const ADMIN = 'admin';
-export const MODERATOR = 'moderator';
-export const AUTHENTICATED = 'authenticated';
-export const ALL = 'normal';
\ No newline at end of file
diff --git a/server/config/config.example.js b/server/config/config.example.js
index 4b8cfe7..1d8baf8 100644
--- a/server/config/config.example.js
+++ b/server/config/config.example.js
@@ -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,
diff --git a/server/lib/Peer.js b/server/lib/Peer.js
index f1dc1a3..2491603 100644
--- a/server/lib/Peer.js
+++ b/server/lib/Peer.js
@@ -27,7 +27,7 @@ class Peer extends EventEmitter
this._authenticated = false;
- this._roles = [ userRoles.ALL ];
+ this._roles = [ userRoles.NORMAL ];
this._displayName = false;
diff --git a/server/lib/Room.js b/server/lib/Room.js
index f2a4e1a..7495e8f 100644
--- a/server/lib/Room.js
+++ b/server/lib/Room.js
@@ -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;
diff --git a/server/server.js b/server/server.js
index 542f3f0..119f8e6 100755
--- a/server/server.js
+++ b/server/server.js
@@ -327,7 +327,7 @@ async function setupAuth()
{
for (const role of peer.roles)
{
- if (role !== userRoles.ALL)
+ if (role !== userRoles.NORMAL)
peer.removeRole(role);
}
}
diff --git a/server/userRoles.js b/server/userRoles.js
index c8cf886..b9d0d2b 100644
--- a/server/userRoles.js
+++ b/server/userRoles.js
@@ -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'
};
\ No newline at end of file