Merge pull request #625 from antobinary/lock-settings
html5client:Lock settings implementation
This commit is contained in:
commit
85d3bca1d1
@ -20,7 +20,6 @@ public class WhiteboardListener implements MessageHandler{
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(String pattern, String channel, String message) {
|
public void handleMessage(String pattern, String channel, String message) {
|
||||||
if (channel.equalsIgnoreCase(MessagingConstants.TO_WHITEBOARD_CHANNEL)) {
|
if (channel.equalsIgnoreCase(MessagingConstants.TO_WHITEBOARD_CHANNEL)) {
|
||||||
System.out.println("AntonChannel=(whiteboard)" + channel);
|
|
||||||
|
|
||||||
JsonParser parser = new JsonParser();
|
JsonParser parser = new JsonParser();
|
||||||
JsonObject obj = (JsonObject) parser.parse(message);
|
JsonObject obj = (JsonObject) parser.parse(message);
|
||||||
@ -44,7 +43,7 @@ public class WhiteboardListener implements MessageHandler{
|
|||||||
else {
|
else {
|
||||||
System.out.println("\n DID NOT FIND A whiteboardID \n");
|
System.out.println("\n DID NOT FIND A whiteboardID \n");
|
||||||
}
|
}
|
||||||
System.out.println("\n\n\n user<" + requesterID + "> requested the shapes.\n\n");
|
System.out.println("\n user<" + requesterID + "> requested the shapes.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,9 @@ class BigBlueButtonActor(outGW: MessageOutGateway) extends Actor with LogHelper
|
|||||||
|
|
||||||
//send chat history
|
//send chat history
|
||||||
this ! (new GetChatHistoryRequest(id, "nodeJSapp", "nodeJSapp"))
|
this ! (new GetChatHistoryRequest(id, "nodeJSapp", "nodeJSapp"))
|
||||||
|
|
||||||
|
//send lock settings
|
||||||
|
this ! (new GetLockSettings(id, "nodeJSapp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
outGW.send(new GetAllMeetingsReply(resultArray))
|
outGW.send(new GetAllMeetingsReply(resultArray))
|
||||||
|
@ -2,7 +2,6 @@ package org.bigbluebutton.core
|
|||||||
|
|
||||||
import scala.actors.Actor
|
import scala.actors.Actor
|
||||||
import scala.actors.Actor._
|
import scala.actors.Actor._
|
||||||
import org.bigbluebutton.core.apps.poll.PollApp
|
|
||||||
import org.bigbluebutton.core.apps.poll.Poll
|
import org.bigbluebutton.core.apps.poll.Poll
|
||||||
import org.bigbluebutton.core.apps.poll.PollApp
|
import org.bigbluebutton.core.apps.poll.PollApp
|
||||||
import org.bigbluebutton.core.apps.users.UsersApp
|
import org.bigbluebutton.core.apps.users.UsersApp
|
||||||
@ -90,6 +89,7 @@ class MeetingActor(val meetingID: String, val externalMeetingID: String, val mee
|
|||||||
case msg: MuteUserRequest => handleMuteUserRequest(msg)
|
case msg: MuteUserRequest => handleMuteUserRequest(msg)
|
||||||
case msg: EjectUserFromVoiceRequest => handleEjectUserRequest(msg)
|
case msg: EjectUserFromVoiceRequest => handleEjectUserRequest(msg)
|
||||||
case msg: SetLockSettings => handleSetLockSettings(msg)
|
case msg: SetLockSettings => handleSetLockSettings(msg)
|
||||||
|
case msg: GetLockSettings => handleGetLockSettings(msg)
|
||||||
case msg: LockUserRequest => handleLockUserRequest(msg)
|
case msg: LockUserRequest => handleLockUserRequest(msg)
|
||||||
case msg: InitLockSettings => handleInitLockSettings(msg)
|
case msg: InitLockSettings => handleInitLockSettings(msg)
|
||||||
case msg: InitAudioSettings => handleInitAudioSettings(msg)
|
case msg: InitAudioSettings => handleInitAudioSettings(msg)
|
||||||
|
@ -81,18 +81,11 @@ trait UsersApp {
|
|||||||
//send the reply
|
//send the reply
|
||||||
outGW.send(new ValidateAuthTokenReply(meetingID, msg.userId, msg.token, true, msg.correlationId, msg.sessionId))
|
outGW.send(new ValidateAuthTokenReply(meetingID, msg.userId, msg.token, true, msg.correlationId, msg.sessionId))
|
||||||
|
|
||||||
//send the list of users in the meeting
|
|
||||||
outGW.send(new GetUsersReply(meetingID, msg.userId, users.getUsers, msg.sessionId))
|
|
||||||
|
|
||||||
//send chat history
|
|
||||||
this ! (new GetChatHistoryRequest(meetingID, msg.userId, msg.userId))
|
|
||||||
|
|
||||||
//join the user
|
//join the user
|
||||||
handleUserJoin(new UserJoining(meetingID, msg.userId, msg.token))
|
handleUserJoin(new UserJoining(meetingID, msg.userId, msg.token))
|
||||||
|
|
||||||
//send the presentation
|
//send the presentation
|
||||||
logger.info("ValidateToken success: mid=[" + meetingID + "] uid=[" + msg.userId + "]")
|
logger.info("ValidateToken success: mid=[" + meetingID + "] uid=[" + msg.userId + "]")
|
||||||
this ! (new GetPresentationInfo(meetingID, msg.userId, msg.userId))
|
|
||||||
}
|
}
|
||||||
case None => {
|
case None => {
|
||||||
logger.info("ValidateToken failed: mid=[" + meetingID + "] uid=[" + msg.userId + "]")
|
logger.info("ValidateToken failed: mid=[" + meetingID + "] uid=[" + msg.userId + "]")
|
||||||
@ -153,11 +146,14 @@ trait UsersApp {
|
|||||||
case None => // do nothing
|
case None => // do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleGetLockSettings(msg: GetLockSettings) {
|
def handleGetLockSettings(msg: GetLockSettings) {
|
||||||
logger.info("Not implemented: handleGetLockSettings")
|
//println("*************** Reply with current lock settings ********************")
|
||||||
|
|
||||||
|
//reusing the existing handle for NewPermissionsSettings to reply to the GetLockSettings request
|
||||||
|
outGW.send(new NewPermissionsSetting(meetingID, msg.userId, permissions, users.getUsers))
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleSetLockSettings(msg: SetLockSettings) {
|
def handleSetLockSettings(msg: SetLockSettings) {
|
||||||
// println("*************** Received new lock settings ********************")
|
// println("*************** Received new lock settings ********************")
|
||||||
if (!permissionsEqual(msg.settings)) {
|
if (!permissionsEqual(msg.settings)) {
|
||||||
|
@ -160,7 +160,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<mx:HBox width="100%" horizontalAlign="right" horizontalGap="18" paddingTop="20">
|
<mx:HBox width="100%" horizontalAlign="right" horizontalGap="18" paddingTop="20">
|
||||||
<mx:Button id="saveBtn" label="{ResourceUtil.getInstance().getString('bbb.lockSettings.save')}"
|
<mx:Button id="saveBtn" label="{ResourceUtil.getInstance().getString('bbb.lockSettings.save')}"
|
||||||
click="onSaveClicked()" tabIndex="{baseIndex+8}"
|
click="onSaveClicked()" tabIndex="{baseIndex+8}"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.lockSettings.save.toolTip')}"/>
|
toolTip="{ResourceUtil.getInstance().getString('bbb.lockSettings.save.tooltip')}"/>
|
||||||
|
|
||||||
<mx:Button id="cancelBtn" label="{ResourceUtil.getInstance().getString('bbb.lockSettings.cancel')}"
|
<mx:Button id="cancelBtn" label="{ResourceUtil.getInstance().getString('bbb.lockSettings.cancel')}"
|
||||||
click="onCancelClicked()" tabIndex="{baseIndex+9}"
|
click="onCancelClicked()" tabIndex="{baseIndex+9}"
|
||||||
|
@ -87,6 +87,19 @@ https://github.com/bigbluebutton/bigbluebutton/blob/master/bigbluebutton-client/
|
|||||||
BBB.isUserTalking = (userId, callback) ->
|
BBB.isUserTalking = (userId, callback) ->
|
||||||
BBB.getUser(userId)?.user?.voiceUser?.talking
|
BBB.getUser(userId)?.user?.voiceUser?.talking
|
||||||
|
|
||||||
|
# returns true if the current user is marked as locked
|
||||||
|
BBB.amILocked = () ->
|
||||||
|
return BBB.getCurrentUser()?.user.locked
|
||||||
|
|
||||||
|
# check whether the user is locked AND the current lock settings for the room
|
||||||
|
# includes locking the microphone of viewers (listenOnly is still alowed)
|
||||||
|
BBB.isMyMicLocked = () ->
|
||||||
|
lockedMicForRoom = Meteor.Meetings.findOne()?.roomLockSettings.disableMic
|
||||||
|
# note that voiceUser.locked is not used in BigBlueButton at this stage (April 2015)
|
||||||
|
|
||||||
|
return lockedMicForRoom and BBB.amILocked()
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
Raise user's hand.
|
Raise user's hand.
|
||||||
|
|
||||||
@ -208,6 +221,8 @@ https://github.com/bigbluebutton/bigbluebutton/blob/master/bigbluebutton-client/
|
|||||||
isListenOnly: signifies whether the user joining the conference audio requests to join the listen only stream
|
isListenOnly: signifies whether the user joining the conference audio requests to join the listen only stream
|
||||||
###
|
###
|
||||||
BBB.joinVoiceConference = (callback, isListenOnly) ->
|
BBB.joinVoiceConference = (callback, isListenOnly) ->
|
||||||
|
if BBB.isMyMicLocked()
|
||||||
|
callIntoConference(BBB.getMyVoiceBridge(), callback, true) #true because we force isListenOnly mode
|
||||||
callIntoConference(BBB.getMyVoiceBridge(), callback, isListenOnly)
|
callIntoConference(BBB.getMyVoiceBridge(), callback, isListenOnly)
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -64,8 +64,6 @@ displayAudioSelectionMenu = ({isMobile} = {}) ->
|
|||||||
|
|
||||||
if isMobile
|
if isMobile
|
||||||
toggleSlidingMenu()
|
toggleSlidingMenu()
|
||||||
|
|
||||||
if isMobile
|
|
||||||
$('.navbarTitle').css('width', '55%')
|
$('.navbarTitle').css('width', '55%')
|
||||||
|
|
||||||
# pop open the dialog allowing users to choose the audio options
|
# pop open the dialog allowing users to choose the audio options
|
||||||
@ -73,9 +71,20 @@ displayAudioSelectionMenu = ({isMobile} = {}) ->
|
|||||||
$('.joinAudio-dialog').addClass('landscape-mobile-joinAudio-dialog')
|
$('.joinAudio-dialog').addClass('landscape-mobile-joinAudio-dialog')
|
||||||
else
|
else
|
||||||
$('.joinAudio-dialog').addClass('desktop-joinAudio-dialog')
|
$('.joinAudio-dialog').addClass('desktop-joinAudio-dialog')
|
||||||
|
|
||||||
$("#joinAudioDialog").dialog("open")
|
$("#joinAudioDialog").dialog("open")
|
||||||
|
|
||||||
|
|
||||||
|
# helper function to reuse some code for the handling of audio join
|
||||||
|
onAudioJoinHelper = () ->
|
||||||
|
# if the microphone is locked (lock settings), the viewer is only
|
||||||
|
# allowed to join the audio as listenOnly.
|
||||||
|
if BBB.isMyMicLocked()
|
||||||
|
introToAudio(null, isListenOnly: true)
|
||||||
|
else
|
||||||
|
displayAudioSelectionMenu(isMobile: isMobile())
|
||||||
|
|
||||||
|
|
||||||
# Helper to load javascript libraries from the BBB server
|
# Helper to load javascript libraries from the BBB server
|
||||||
loadLib = (libname) ->
|
loadLib = (libname) ->
|
||||||
successCallback = ->
|
successCallback = ->
|
||||||
@ -113,7 +122,7 @@ Template.footer.helpers
|
|||||||
|
|
||||||
Template.header.events
|
Template.header.events
|
||||||
"click .joinAudioButton": (event) ->
|
"click .joinAudioButton": (event) ->
|
||||||
displayAudioSelectionMenu(isMobile: false)
|
onAudioJoinHelper()
|
||||||
|
|
||||||
"click .chatBarIcon": (event) ->
|
"click .chatBarIcon": (event) ->
|
||||||
$(".tooltip").hide()
|
$(".tooltip").hide()
|
||||||
@ -186,7 +195,7 @@ Template.header.events
|
|||||||
|
|
||||||
Template.slidingMenu.events
|
Template.slidingMenu.events
|
||||||
'click .joinAudioButton': (event) ->
|
'click .joinAudioButton': (event) ->
|
||||||
displayAudioSelectionMenu(isMobile: true)
|
onAudioJoinHelper()
|
||||||
|
|
||||||
'click .chatBarIcon': (event) ->
|
'click .chatBarIcon': (event) ->
|
||||||
$('.tooltip').hide()
|
$('.tooltip').hide()
|
||||||
@ -319,7 +328,7 @@ Template.main.rendered = ->
|
|||||||
toggleSlidingMenu()
|
toggleSlidingMenu()
|
||||||
|
|
||||||
if Meteor.config.app.autoJoinAudio
|
if Meteor.config.app.autoJoinAudio
|
||||||
displayAudioSelectionMenu(isMobile:isMobile())
|
onAudioJoinHelper()
|
||||||
|
|
||||||
Template.makeButton.rendered = ->
|
Template.makeButton.rendered = ->
|
||||||
$('button[rel=tooltip]').tooltip()
|
$('button[rel=tooltip]').tooltip()
|
||||||
|
@ -119,6 +119,12 @@
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.disabledChat {
|
||||||
|
background-color: grey;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
float: left;
|
float: left;
|
||||||
@media @desktop-portrait, @mobile-portrait, @mobile-portrait-with-keyboard {
|
@media @desktop-portrait, @mobile-portrait, @mobile-portrait-with-keyboard {
|
||||||
|
@ -65,6 +65,24 @@ Handlebars.registerHelper "grabChatTabs", ->
|
|||||||
setInSession 'chatTabs', initTabs
|
setInSession 'chatTabs', initTabs
|
||||||
getInSession('chatTabs')[0..3]
|
getInSession('chatTabs')[0..3]
|
||||||
|
|
||||||
|
# true if the lock settings limit public chat and the current user is locked
|
||||||
|
Handlebars.registerHelper "publicChatDisabled", ->
|
||||||
|
userIsLocked = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.locked
|
||||||
|
publicChatIsDisabled = Meteor.Meetings.findOne({})?.roomLockSettings.disablePubChat
|
||||||
|
presenter = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.presenter
|
||||||
|
return userIsLocked and publicChatIsDisabled and !presenter
|
||||||
|
|
||||||
|
# true if the lock settings limit private chat and the current user is locked
|
||||||
|
Handlebars.registerHelper "privateChatDisabled", ->
|
||||||
|
userIsLocked = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.locked
|
||||||
|
privateChatIsDisabled = Meteor.Meetings.findOne({})?.roomLockSettings.disablePrivChat
|
||||||
|
presenter = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.presenter
|
||||||
|
return userIsLocked and privateChatIsDisabled and !presenter
|
||||||
|
|
||||||
|
# return whether the user's chat pane is open in Private chat (vs Public chat or Options)
|
||||||
|
Handlebars.registerHelper "inPrivateChat", ->
|
||||||
|
return !((getInSession 'inChatWith') in ['PUBLIC_CHAT', 'OPTIONS'])
|
||||||
|
|
||||||
@sendMessage = ->
|
@sendMessage = ->
|
||||||
message = linkify $('#newMessageInput').val() # get the message from the input box
|
message = linkify $('#newMessageInput').val() # get the message from the input box
|
||||||
unless (message?.length > 0 and (/\S/.test(message))) # check the message has content and it is not whitespace
|
unless (message?.length > 0 and (/\S/.test(message))) # check the message has content and it is not whitespace
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
<div id="{{id}}" {{visibility name}} class="component">
|
<div id="{{id}}" {{visibility name}} class="component">
|
||||||
<h3 class="title gradientBar">
|
<h3 class="title gradientBar">
|
||||||
<span class="glyphicon glyphicon-comment heading"></span>
|
<span class="glyphicon glyphicon-comment heading"></span>
|
||||||
{{title}}
|
|
||||||
{{> extraConversations}}
|
{{> extraConversations}}
|
||||||
</h3>
|
</h3>
|
||||||
{{>tabButtons}} <!-- Display public/options tabs, and private chat tabs -->
|
{{>tabButtons}} <!-- Display public/options tabs, and private chat tabs -->
|
||||||
@ -28,10 +27,25 @@
|
|||||||
|
|
||||||
<template name="chatInput">
|
<template name="chatInput">
|
||||||
<div id="chatInput" class="chat-input-wrapper">
|
<div id="chatInput" class="chat-input-wrapper">
|
||||||
<textarea id="newMessageInput" placeholder="Write a message..." rel="tooltip" data-placement="top" title="Write a new message"></textarea>
|
{{#if inPrivateChat}}
|
||||||
<button type="submit" id="sendMessageButton" class="btn" rel="tooltip" data-placement="top">
|
{{#if privateChatDisabled}}
|
||||||
Send
|
<textarea id="newMessageInput" class="disabledChat" placeholder="Private chat is temporarily locked (disabled)" rel="tooltip" data-placement="top" title="Private chat is temporarily locked" disabled></textarea>
|
||||||
</button>
|
{{else}}
|
||||||
|
<textarea id="newMessageInput" placeholder="Write a message..." rel="tooltip" data-placement="top" title="Write a new message"></textarea>
|
||||||
|
<button type="submit" id="sendMessageButton" class="btn" rel="tooltip" data-placement="top">
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if publicChatDisabled}}
|
||||||
|
<textarea id="newMessageInput" class="disabledChat" placeholder="Public chat is temporarily locked (disabled)" rel="tooltip" data-placement="top" title="Public chat is temporarily locked" disabled></textarea>
|
||||||
|
{{else}}
|
||||||
|
<textarea id="newMessageInput" placeholder="Write a message..." rel="tooltip" data-placement="top" title="Write a new message"></textarea>
|
||||||
|
<button type="submit" id="sendMessageButton" class="btn" rel="tooltip" data-placement="top">
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -9,3 +9,16 @@ Template.displayUserIcons.events
|
|||||||
# the userId of the person who is lowering the hand
|
# the userId of the person who is lowering the hand
|
||||||
console.log "lower hand- client click handler"
|
console.log "lower hand- client click handler"
|
||||||
Meteor.call('userLowerHand', getInSession("meetingId"), @userId, getInSession("userId"), getInSession("authToken"))
|
Meteor.call('userLowerHand', getInSession("meetingId"), @userId, getInSession("userId"), getInSession("authToken"))
|
||||||
|
|
||||||
|
Template.displayUserIcons.helpers
|
||||||
|
userLockedIconApplicable: (userId) ->
|
||||||
|
# the lock settings affect the user (and requiire a lock icon) if
|
||||||
|
# the user is set to be locked and there is a relevant lock in place
|
||||||
|
locked = BBB.getUser(userId)?.user.locked
|
||||||
|
settings = Meteor.Meetings.findOne()?.roomLockSettings
|
||||||
|
lockInAction = settings.disablePrivChat or
|
||||||
|
settings.disableCam or
|
||||||
|
settings.disableMic or
|
||||||
|
settings.lockedLayout or
|
||||||
|
settings.disablePubChat
|
||||||
|
return locked and lockInAction
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if userLockedIconApplicable userId}}
|
||||||
|
<span class="userListSettingIcon glyphicon ion-locked" rel="tooltip" data-placement="bottom" title="The viewer is locked"></span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if user.presenter}}
|
{{#if user.presenter}}
|
||||||
<span class="userListSettingIcon glyphicon glyphicon-picture" rel="tooltip" data-placement="bottom" title="{{user.name}} is the presenter"></span>
|
<span class="userListSettingIcon glyphicon glyphicon-picture" rel="tooltip" data-placement="bottom" title="{{user.name}} is the presenter"></span>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -14,6 +14,8 @@ config.defaultWelcomeMessageFooter = "This server is running a build of <a href=
|
|||||||
config.maxUsernameLength = 30
|
config.maxUsernameLength = 30
|
||||||
config.maxChatLength = 140
|
config.maxChatLength = 140
|
||||||
|
|
||||||
|
config.lockOnJoin = true
|
||||||
|
|
||||||
## Application configurations
|
## Application configurations
|
||||||
config.app = {}
|
config.app = {}
|
||||||
|
|
||||||
|
@ -2,17 +2,27 @@
|
|||||||
# Private methods on server
|
# Private methods on server
|
||||||
# --------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------
|
||||||
@addMeetingToCollection = (meetingId, name, intendedForRecording, voiceConf, duration) ->
|
@addMeetingToCollection = (meetingId, name, intendedForRecording, voiceConf, duration) ->
|
||||||
#check if the meeting is already in the collection
|
#check if the meeting is already in the collection
|
||||||
unless Meteor.Meetings.findOne({meetingId: meetingId})?
|
unless Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||||
currentlyBeingRecorded = false # defaut value
|
entry =
|
||||||
id = Meteor.Meetings.insert(
|
meetingId: meetingId
|
||||||
meetingId: meetingId,
|
meetingName: name
|
||||||
meetingName: name,
|
intendedForRecording: intendedForRecording
|
||||||
intendedForRecording: intendedForRecording,
|
currentlyBeingRecorded: false # defaut value
|
||||||
currentlyBeingRecorded: currentlyBeingRecorded,
|
voiceConf: voiceConf
|
||||||
voiceConf: voiceConf,
|
duration: duration
|
||||||
duration: duration)
|
roomLockSettings:
|
||||||
Meteor.log.info "added meeting _id=[#{id}]:meetingId=[#{meetingId}]:name=[#{name}]:duration=[#{duration}]:voiceConf=[#{voiceConf}]."
|
# by default the lock settings will be disabled on meeting create
|
||||||
|
disablePrivChat: false
|
||||||
|
disableCam: false
|
||||||
|
disableMic: false
|
||||||
|
lockOnJoin: Meteor.config.lockOnJoin
|
||||||
|
lockedLayout: false
|
||||||
|
disablePubChat: false
|
||||||
|
|
||||||
|
id = Meteor.Meetings.insert(entry)
|
||||||
|
Meteor.log.info "added meeting _id=[#{id}]:meetingId=[#{meetingId}]:name=[#{name}]:duration=[#{duration}]:voiceConf=[#{voiceConf}]
|
||||||
|
roomLockSettings:[#{JSON.stringify entry.roomLockSettings}]."
|
||||||
|
|
||||||
|
|
||||||
@clearMeetingsCollection = (meetingId) ->
|
@clearMeetingsCollection = (meetingId) ->
|
||||||
@ -22,6 +32,7 @@
|
|||||||
Meteor.Meetings.remove({}, Meteor.log.info "cleared Meetings Collection (all meetings)!")
|
Meteor.Meetings.remove({}, Meteor.log.info "cleared Meetings Collection (all meetings)!")
|
||||||
|
|
||||||
|
|
||||||
|
#clean up upon a meeting's end
|
||||||
@removeMeetingFromCollection = (meetingId) ->
|
@removeMeetingFromCollection = (meetingId) ->
|
||||||
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||||
Meteor.log.info "end of meeting #{meetingId}. Clear the meeting data from all collections"
|
Meteor.log.info "end of meeting #{meetingId}. Clear the meeting data from all collections"
|
||||||
|
@ -204,7 +204,7 @@ Meteor.methods
|
|||||||
# the collection already contains an entry for this user because
|
# the collection already contains an entry for this user because
|
||||||
# we added a dummy user on register_user_message (to save authToken)
|
# we added a dummy user on register_user_message (to save authToken)
|
||||||
if u?
|
if u?
|
||||||
Meteor.log.info "UPDATING USER #{user.userid}, authToken=#{u.authToken}"
|
Meteor.log.info "UPDATING USER #{user.userid}, authToken=#{u.authToken}, locked=#{user.locked}"
|
||||||
Meteor.Users.update({userId:user.userid, meetingId: meetingId}, {$set:{
|
Meteor.Users.update({userId:user.userid, meetingId: meetingId}, {$set:{
|
||||||
user:
|
user:
|
||||||
userid: user.userid
|
userid: user.userid
|
||||||
@ -308,6 +308,36 @@ Meteor.methods
|
|||||||
Meteor.log.info "added user dummy html5 user with: userid=[#{userId}], id=[#{id}]
|
Meteor.log.info "added user dummy html5 user with: userid=[#{userId}], id=[#{id}]
|
||||||
Users.size is now #{Meteor.Users.find({meetingId: meetingId}).count()}"
|
Users.size is now #{Meteor.Users.find({meetingId: meetingId}).count()}"
|
||||||
|
|
||||||
|
|
||||||
|
# when new lock settings including disableMic are set,
|
||||||
|
# all viewers that are in the audio bridge with a mic should be muted and locked
|
||||||
|
@handleLockingMic = (meetingId, newSettings) ->
|
||||||
|
# send mute requests for the viewer users joined with mic
|
||||||
|
for u in Meteor.Users.find({
|
||||||
|
meetingId:meetingId
|
||||||
|
'user.role':'VIEWER'
|
||||||
|
'user.listenOnly':false
|
||||||
|
'user.locked':true
|
||||||
|
'user.voiceUser.joined':true
|
||||||
|
'user.voiceUser.muted':false})?.fetch()
|
||||||
|
Meteor.log.error u.user.name #
|
||||||
|
Meteor.call('muteUser', meetingId, u.userId, u.userId, u.authToken, true) #true for muted
|
||||||
|
|
||||||
|
# change the locked status of a user (lock settings)
|
||||||
|
@setUserLockedStatus = (meetingId, userId, isLocked) ->
|
||||||
|
if Meteor.Users.findOne({userId:userId, meetingId: meetingId})?
|
||||||
|
Meteor.Users.update({userId:userId, meetingId: meetingId}, {$set:{'user.locked': isLocked}})
|
||||||
|
|
||||||
|
# if the user is sharing audio, he should be muted upon locking involving disableMic
|
||||||
|
u = Meteor.Users.findOne({meetingId:meetingId, userId:userId})
|
||||||
|
if u.user.role is 'VIEWER' and !u.user.listenOnly and u.user.voiceUser.joined and !u.user.voiceUser.muted and isLocked
|
||||||
|
Meteor.call('muteUser', meetingId, u.userId, u.userId, u.authToken, true) #true for muted
|
||||||
|
|
||||||
|
Meteor.log.info "setting user locked status for userid:[#{userId}] from [#{meetingId}] locked=#{isLocked}"
|
||||||
|
else
|
||||||
|
Meteor.log.error "(unsuccessful-no such user) setting user locked status for userid:[#{userId}] from [#{meetingId}] locked=#{isLocked}"
|
||||||
|
|
||||||
|
|
||||||
# called on server start and on meeting end
|
# called on server start and on meeting end
|
||||||
@clearUsersCollection = (meetingId) ->
|
@clearUsersCollection = (meetingId) ->
|
||||||
if meetingId?
|
if meetingId?
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
Meteor.methods
|
Meteor.methods
|
||||||
#
|
|
||||||
# I dont know if this is okay to be server side. We need to call it from the router, but I don't know if any harm can be caused
|
|
||||||
# by the client calling this
|
|
||||||
#
|
|
||||||
|
|
||||||
# Construct and send a message to bbb-web to validate the user
|
# Construct and send a message to bbb-web to validate the user
|
||||||
validateAuthToken: (meetingId, userId, authToken) ->
|
validateAuthToken: (meetingId, userId, authToken) ->
|
||||||
@ -60,15 +56,25 @@ class Meteor.RedisPubSub
|
|||||||
correlationId = message.payload?.reply_to or message.header?.reply_to
|
correlationId = message.payload?.reply_to or message.header?.reply_to
|
||||||
meetingId = message.payload?.meeting_id
|
meetingId = message.payload?.meeting_id
|
||||||
|
|
||||||
ignoredEventTypes = [
|
# just because it's common. we handle it anyway
|
||||||
|
notLoggedEventTypes = [
|
||||||
"keep_alive_reply"
|
"keep_alive_reply"
|
||||||
"page_resized_message"
|
"page_resized_message"
|
||||||
"presentation_page_resized_message"
|
"presentation_page_resized_message"
|
||||||
"presentation_cursor_updated_message" # just because it's common. we handle it anyway
|
"presentation_cursor_updated_message"
|
||||||
|
"get_presentation_info_reply"
|
||||||
|
# "get_users_reply"
|
||||||
|
"get_chat_history_reply"
|
||||||
|
"get_all_meetings_reply"
|
||||||
|
"presentation_shared_message"
|
||||||
|
"presentation_conversion_done_message"
|
||||||
|
"presentation_conversion_progress_message"
|
||||||
|
"presentation_page_generated_message"
|
||||||
|
"presentation_page_changed_message"
|
||||||
]
|
]
|
||||||
|
|
||||||
if message?.header? and message?.payload?
|
if message?.header? and message?.payload?
|
||||||
unless message.header.name in ignoredEventTypes
|
unless message.header.name in notLoggedEventTypes
|
||||||
Meteor.log.info "eventType= #{message.header.name} ",
|
Meteor.log.info "eventType= #{message.header.name} ",
|
||||||
message: jsonMsg
|
message: jsonMsg
|
||||||
|
|
||||||
@ -281,6 +287,37 @@ class Meteor.RedisPubSub
|
|||||||
Meteor.Meetings.update({meetingId: meetingId, intendedForRecording: intendedForRecording}, {$set: {currentlyBeingRecorded: currentlyBeingRecorded}})
|
Meteor.Meetings.update({meetingId: meetingId, intendedForRecording: intendedForRecording}, {$set: {currentlyBeingRecorded: currentlyBeingRecorded}})
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
# lock settings ------------------------------------
|
||||||
|
if message.header.name is "eject_voice_user_message"
|
||||||
|
console.log "\n111111111"
|
||||||
|
return
|
||||||
|
|
||||||
|
if message.header.name is "new_permission_settings"
|
||||||
|
oldSettings = Meteor.Meetings.findOne({meetingId:meetingId})?.roomLockSettings
|
||||||
|
newSettings = message.payload
|
||||||
|
|
||||||
|
# if the disableMic setting was turned on
|
||||||
|
if !oldSettings?.disableMic and newSettings.disableMic
|
||||||
|
handleLockingMic(meetingId, newSettings)
|
||||||
|
|
||||||
|
# substitute with the new lock settings
|
||||||
|
Meteor.Meetings.update({meetingId: meetingId}, {$set: {
|
||||||
|
'roomLockSettings.disablePrivChat': message.payload.disablePrivChat
|
||||||
|
'roomLockSettings.disableCam': message.payload.disableCam
|
||||||
|
'roomLockSettings.disableMic': message.payload.disableMic
|
||||||
|
'roomLockSettings.lockOnJoin': message.payload.lockOnJoin
|
||||||
|
'roomLockSettings.lockedLayout': message.payload.lockedLayout
|
||||||
|
'roomLockSettings.disablePubChat': message.payload.disablePubChat
|
||||||
|
}})
|
||||||
|
return
|
||||||
|
|
||||||
|
if message.header.name is "user_locked_message" or message.header.name is "user_unlocked_message"
|
||||||
|
userId = message.payload.userid
|
||||||
|
isLocked = message.payload.locked
|
||||||
|
setUserLockedStatus(meetingId, userId, isLocked)
|
||||||
|
return
|
||||||
|
|
||||||
if message.header.name in ["meeting_ended_message", "meeting_destroyed_event",
|
if message.header.name in ["meeting_ended_message", "meeting_destroyed_event",
|
||||||
"end_and_kick_all_message", "disconnect_all_users_message"]
|
"end_and_kick_all_message", "disconnect_all_users_message"]
|
||||||
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||||
@ -298,9 +335,9 @@ class Meteor.RedisPubSub
|
|||||||
|
|
||||||
# message should be an object
|
# message should be an object
|
||||||
@publish = (channel, message) ->
|
@publish = (channel, message) ->
|
||||||
Meteor.log.info "Publishing",
|
# Meteor.log.info "Publishing",
|
||||||
channel: channel
|
# channel: channel
|
||||||
message: message
|
# message: message
|
||||||
|
|
||||||
if Meteor.redisPubSub?
|
if Meteor.redisPubSub?
|
||||||
Meteor.redisPubSub.pubClient.publish channel, JSON.stringify(message), (err, res) ->
|
Meteor.redisPubSub.pubClient.publish channel, JSON.stringify(message), (err, res) ->
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
|
|
||||||
presenter = null
|
presenter = null
|
||||||
|
|
||||||
#for the time being moderators have the same permissions that viewers do
|
# holds the values for whether the moderator user is allowed to perform an action (true)
|
||||||
|
# or false if not allowed. Some actions have dynamic values depending on the current lock settings
|
||||||
moderator =
|
moderator =
|
||||||
|
# audio listen only
|
||||||
|
joinListenOnly: true
|
||||||
|
leaveListenOnly: true
|
||||||
|
|
||||||
|
# join audio with mic cannot be controlled on the server side as it is
|
||||||
|
# a client side only functionality
|
||||||
|
|
||||||
# raising/lowering hand
|
# raising/lowering hand
|
||||||
raiseOwnHand : true
|
raiseOwnHand : true
|
||||||
lowerOwnHand : true
|
lowerOwnHand : true
|
||||||
@ -18,21 +26,29 @@ moderator =
|
|||||||
subscribeChat: true
|
subscribeChat: true
|
||||||
|
|
||||||
#chat
|
#chat
|
||||||
chatPublic: true #should make this dynamically modifiable later on
|
chatPublic: true
|
||||||
chatPrivate: true #should make this dynamically modifiable later on
|
chatPrivate: true
|
||||||
|
|
||||||
|
|
||||||
|
# holds the values for whether the viewer user is allowed to perform an action (true)
|
||||||
|
# or false if not allowed. Some actions have dynamic values depending on the current lock settings
|
||||||
|
viewer = (meetingId, userId) ->
|
||||||
|
|
||||||
# listen only
|
# listen only
|
||||||
joinListenOnly: true #should make this dynamically modifiable later on
|
joinListenOnly: true
|
||||||
leaveListenOnly: true #should make this dynamically modifiable later on
|
leaveListenOnly: true
|
||||||
|
|
||||||
|
# join audio with mic cannot be controlled on the server side as it is
|
||||||
|
# a client side only functionality
|
||||||
|
|
||||||
viewer =
|
|
||||||
# raising/lowering hand
|
# raising/lowering hand
|
||||||
raiseOwnHand : true
|
raiseOwnHand : true
|
||||||
lowerOwnHand : true
|
lowerOwnHand : true
|
||||||
|
|
||||||
# muting
|
# muting
|
||||||
muteSelf : true
|
muteSelf : true
|
||||||
unmuteSelf : true
|
unmuteSelf : !(Meteor.Meetings.findOne({meetingId:meetingId})?.roomLockSettings.disableMic) or
|
||||||
|
!(Meteor.Users.findOne({meetingId:meetingId, userId:userId})?.user.locked)
|
||||||
|
|
||||||
logoutSelf : true
|
logoutSelf : true
|
||||||
|
|
||||||
@ -41,15 +57,18 @@ viewer =
|
|||||||
subscribeChat: true
|
subscribeChat: true
|
||||||
|
|
||||||
#chat
|
#chat
|
||||||
chatPublic: true #should make this dynamically modifiable later on
|
chatPublic: !(Meteor.Meetings.findOne({meetingId:meetingId})?.roomLockSettings.disablePubChat) or
|
||||||
chatPrivate: true #should make this dynamically modifiable later on
|
!(Meteor.Users.findOne({meetingId:meetingId, userId:userId})?.user.locked) or
|
||||||
|
Meteor.Users.findOne({meetingId:meetingId, userId:userId})?.user.presenter
|
||||||
|
chatPrivate: !(Meteor.Meetings.findOne({meetingId:meetingId})?.roomLockSettings.disablePrivChat) or
|
||||||
|
!(Meteor.Users.findOne({meetingId:meetingId, userId:userId})?.user.locked) or
|
||||||
|
Meteor.Users.findOne({meetingId:meetingId, userId:userId})?.user.presenter
|
||||||
|
|
||||||
# listen only
|
|
||||||
joinListenOnly: true #should make this dynamically modifiable later on
|
|
||||||
leaveListenOnly: true #should make this dynamically modifiable later on
|
|
||||||
|
|
||||||
|
|
||||||
|
# carries out the decision making for actions affecting users. For the list of
|
||||||
|
# actions and the default value - see 'viewer' and 'moderator' in the beginning of the file
|
||||||
@isAllowedTo = (action, meetingId, userId, authToken) ->
|
@isAllowedTo = (action, meetingId, userId, authToken) ->
|
||||||
# Disclaimer:the current version of the HTML5 client represents only VIEWER users
|
|
||||||
|
|
||||||
validated = Meteor.Users.findOne({meetingId:meetingId, userId: userId})?.validated
|
validated = Meteor.Users.findOne({meetingId:meetingId, userId: userId})?.validated
|
||||||
Meteor.log.info "in isAllowedTo: action-#{action}, userId=#{userId}, authToken=#{authToken} validated:#{validated}"
|
Meteor.log.info "in isAllowedTo: action-#{action}, userId=#{userId}, authToken=#{authToken} validated:#{validated}"
|
||||||
@ -59,7 +78,7 @@ viewer =
|
|||||||
if user? and authToken is user.authToken # check if the user is who he claims to be
|
if user? and authToken is user.authToken # check if the user is who he claims to be
|
||||||
if user.validated and user.clientType is "HTML5"
|
if user.validated and user.clientType is "HTML5"
|
||||||
if user.user?.role is 'VIEWER' or user.user?.role is 'MODERATOR' or user.user?.role is undefined
|
if user.user?.role is 'VIEWER' or user.user?.role is 'MODERATOR' or user.user?.role is undefined
|
||||||
return viewer[action] or false
|
return viewer(meetingId, userId)[action] or false
|
||||||
else
|
else
|
||||||
Meteor.log.warn "UNSUCCESSFULL ATTEMPT FROM userid=#{userId} to perform:#{action}"
|
Meteor.log.warn "UNSUCCESSFULL ATTEMPT FROM userid=#{userId} to perform:#{action}"
|
||||||
return false
|
return false
|
||||||
|
Loading…
Reference in New Issue
Block a user