Merge branch 'master' of github.com:bigbluebutton/bigbluebutton into guest-work

This commit is contained in:
Anton Georgiev 2017-11-09 15:45:40 -05:00
commit 7b940bd96f
53 changed files with 777 additions and 389 deletions

View File

@ -87,4 +87,14 @@ class CaptionModel {
}
rtnTranscript
}
def isUserCaptionOwner(userId: String, locale: String): Boolean = {
var isOwner: Boolean = false;
if (transcripts.contains(locale) && transcripts(locale).ownerId == userId) {
isOwner = true;
}
isOwner
}
}

View File

@ -3,23 +3,32 @@ package org.bigbluebutton.core.apps.breakout
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.apps.BreakoutModel
import org.bigbluebutton.core.domain.{ BreakoutRoom2x, MeetingState2x }
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.running.MeetingActor
import org.bigbluebutton.core.apps.PermissionCheck
trait CreateBreakoutRoomsCmdMsgHdlr {
this: BaseMeetingActor =>
this: MeetingActor =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleCreateBreakoutRoomsCmdMsg(msg: CreateBreakoutRoomsCmdMsg, state: MeetingState2x): MeetingState2x = {
state.breakout match {
case Some(breakout) =>
log.warning(
"CreateBreakoutRooms event received while breakout created for meeting {}", liveMeeting.props.meetingProp.intId
)
state
case None =>
processRequest(msg, state)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to create breakout room for meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
state
} else {
state.breakout match {
case Some(breakout) =>
log.warning(
"CreateBreakoutRooms event received while breakout created for meeting {}", liveMeeting.props.meetingProp.intId
)
state
case None =>
processRequest(msg, state)
}
}
}

View File

@ -5,6 +5,7 @@ import org.bigbluebutton.core.api.EndBreakoutRoomInternalMsg
import org.bigbluebutton.core.bus.BigBlueButtonEvent
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
import org.bigbluebutton.core.apps.PermissionCheck
trait EndAllBreakoutRoomsMsgHdlr {
this: MeetingActor =>
@ -12,15 +13,21 @@ trait EndAllBreakoutRoomsMsgHdlr {
val outGW: OutMsgRouter
def handleEndAllBreakoutRoomsMsg(msg: EndAllBreakoutRoomsMsg, state: MeetingState2x): MeetingState2x = {
for {
model <- state.breakout
} yield {
model.rooms.values.foreach { room =>
eventBus.publish(BigBlueButtonEvent(room.id, EndBreakoutRoomInternalMsg(props.breakoutProps.parentId, room.id)))
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to end breakout rooms for meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
state
} else {
for {
model <- state.breakout
} yield {
model.rooms.values.foreach { room =>
eventBus.publish(BigBlueButtonEvent(room.id, EndBreakoutRoomInternalMsg(props.breakoutProps.parentId, room.id)))
}
}
}
state.update(None)
state.update(None)
}
}
}

View File

@ -3,6 +3,7 @@ package org.bigbluebutton.core.apps.breakout
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
import org.bigbluebutton.core.apps.PermissionCheck
trait RequestBreakoutJoinURLReqMsgHdlr extends BreakoutHdlrHelpers {
this: MeetingActor =>
@ -10,12 +11,17 @@ trait RequestBreakoutJoinURLReqMsgHdlr extends BreakoutHdlrHelpers {
val outGW: OutMsgRouter
def handleRequestBreakoutJoinURLReqMsg(msg: RequestBreakoutJoinURLReqMsg, state: MeetingState2x): MeetingState2x = {
for {
model <- state.breakout
room <- model.find(msg.body.breakoutId)
} yield {
sendJoinURL(msg.body.userId, room.externalId, room.sequence.toString(), room.id)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to request breakout room URL for meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
} else {
for {
model <- state.breakout
room <- model.find(msg.body.breakoutId)
} yield {
sendJoinURL(msg.body.userId, room.externalId, room.sequence.toString(), room.id)
}
}
state

View File

@ -5,6 +5,7 @@ import org.bigbluebutton.core.apps.BreakoutModel
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.{ VoiceUsers }
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
import org.bigbluebutton.core.apps.PermissionCheck
trait TransferUserToMeetingRequestHdlr {
this: MeetingActor =>
@ -12,7 +13,18 @@ trait TransferUserToMeetingRequestHdlr {
val outGW: OutMsgRouter
def handleTransferUserToMeetingRequestMsg(msg: TransferUserToMeetingRequestMsg, state: MeetingState2x): MeetingState2x = {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to transfer user to voice breakout."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
} else {
processRequest(msg)
}
state
}
def processRequest(msg: TransferUserToMeetingRequestMsg) {
if (msg.body.fromMeetingId == liveMeeting.props.meetingProp.intId) {
// want to transfer from parent meeting to breakout
for {
@ -46,8 +58,6 @@ trait TransferUserToMeetingRequestHdlr {
outGW.send(event)
}
}
state
}
def buildTransferUserToVoiceConfSysMsg(fromVoiceConf: String, toVoiceConf: String, voiceUserId: String): BbbCommonEnvCoreMsg = {

View File

@ -5,8 +5,10 @@ import akka.event.Logging
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
import org.bigbluebutton.SystemConfiguration
import org.bigbluebutton.core.apps.PermissionCheck
class CaptionApp2x(implicit val context: ActorContext) {
class CaptionApp2x(implicit val context: ActorContext) extends SystemConfiguration {
val log = Logging(context.system, getClass)
def getCaptionHistory(liveMeeting: LiveMeeting): Map[String, TranscriptVO] = {
@ -25,6 +27,10 @@ class CaptionApp2x(implicit val context: ActorContext) {
liveMeeting.captionModel.checkCaptionOwnerLogOut(userId)
}
def isUserCaptionOwner(liveMeeting: LiveMeeting, userId: String, locale: String): Boolean = {
liveMeeting.captionModel.isUserCaptionOwner(userId, locale)
}
def handle(msg: EditCaptionHistoryPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
def broadcastEvent(msg: EditCaptionHistoryPubMsg): Unit = {
val routing = Routing.addMsgToClientRouting(
@ -40,10 +46,17 @@ class CaptionApp2x(implicit val context: ActorContext) {
bus.outGW.send(msgEvent)
}
val successfulEdit = editCaptionHistory(liveMeeting, msg.header.userId, msg.body.startIndex,
msg.body.endIndex, msg.body.locale, msg.body.text)
if (successfulEdit) {
broadcastEvent(msg)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)
&& isUserCaptionOwner(liveMeeting, msg.header.userId, msg.body.locale)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to edit caption history in meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
val successfulEdit = editCaptionHistory(liveMeeting, msg.header.userId, msg.body.startIndex,
msg.body.endIndex, msg.body.locale, msg.body.text)
if (successfulEdit) {
broadcastEvent(msg)
}
}
}
@ -74,9 +87,15 @@ class CaptionApp2x(implicit val context: ActorContext) {
bus.outGW.send(msgEvent)
}
updateCaptionOwner(liveMeeting, msg.body.locale, msg.body.localeCode, msg.body.ownerId).foreach(f => {
broadcastUpdateCaptionOwnerEvent(f._1, f._2.localeCode, f._2.ownerId)
})
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to change caption owners."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
updateCaptionOwner(liveMeeting, msg.body.locale, msg.body.localeCode, msg.body.ownerId).foreach(f => {
broadcastUpdateCaptionOwnerEvent(f._1, f._2.localeCode, f._2.ownerId)
})
}
}
def handleUserLeavingMsg(userId: String, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {

View File

@ -5,35 +5,62 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.GroupChat
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core.models.Roles
import org.bigbluebutton.core2.MeetingStatus2x
trait CreateGroupChatReqMsgHdlr {
trait CreateGroupChatReqMsgHdlr extends SystemConfiguration {
this: GroupChatHdlrs =>
def handle(msg: CreateGroupChatReqMsg, state: MeetingState2x,
liveMeeting: LiveMeeting, bus: MessageBus): MeetingState2x = {
log.debug("RECEIVED CREATE CHAT REQ MESSAGE")
val newState = for {
createdBy <- GroupChatApp.findGroupChatUser(msg.header.userId, liveMeeting.users2x)
var chatLocked: Boolean = false;
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId)
} yield {
val msgs = msg.body.msg.map(m => GroupChatApp.toGroupChatMessage(createdBy, m))
val users = {
if (user.role != Roles.MODERATOR_ROLE && user.locked) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
if (msg.body.access == GroupChatAccess.PRIVATE) {
val cu = msg.body.users.toSet + msg.body.requesterId
cu.flatMap(u => GroupChatApp.findGroupChatUser(u, liveMeeting.users2x)).toVector
chatLocked = permissions.disablePrivChat
} else {
Vector.empty
chatLocked = permissions.disablePubChat
}
}
val gc = GroupChatApp.createGroupChat(msg.body.name, msg.body.access, createdBy, users, msgs)
sendMessages(msg, gc, liveMeeting, bus)
val groupChats = state.groupChats.add(gc)
state.update(groupChats)
}
newState.getOrElse(state)
if (applyPermissionCheck && chatLocked) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to create a new group chat."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {
val newState = for {
createdBy <- GroupChatApp.findGroupChatUser(msg.header.userId, liveMeeting.users2x)
} yield {
val msgs = msg.body.msg.map(m => GroupChatApp.toGroupChatMessage(createdBy, m))
val users = {
if (msg.body.access == GroupChatAccess.PRIVATE) {
val cu = msg.body.users.toSet + msg.body.requesterId
cu.flatMap(u => GroupChatApp.findGroupChatUser(u, liveMeeting.users2x)).toVector
} else {
Vector.empty
}
}
val gc = GroupChatApp.createGroupChat(msg.body.name, msg.body.access, createdBy, users, msgs)
sendMessages(msg, gc, liveMeeting, bus)
val groupChats = state.groupChats.add(gc)
state.update(groupChats)
}
newState.getOrElse(state)
}
}
def sendMessages(msg: CreateGroupChatReqMsg, gc: GroupChat,

View File

@ -5,6 +5,10 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.GroupChatMessage
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core2.MeetingStatus2x
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.core.models.Roles
trait SendGroupChatMessageMsgHdlr {
this: GroupChatHdlrs =>
@ -15,63 +19,85 @@ trait SendGroupChatMessageMsgHdlr {
log.debug("RECEIVED PUBLIC CHAT MESSAGE")
log.debug("NUM GROUP CHATS = " + state.groupChats.findAllPublicChats().length)
def makeHeader(name: String, meetingId: String, userId: String): BbbClientMsgHeader = {
BbbClientMsgHeader(name, meetingId, userId)
}
var chatLocked: Boolean = false;
def makeEnvelope(msgType: String, name: String, meetingId: String, userId: String): BbbCoreEnvelope = {
val routing = Routing.addMsgToClientRouting(msgType, meetingId, userId)
BbbCoreEnvelope(name, routing)
}
def buildGroupChatMessageBroadcastEvtMsg(meetingId: String, userId: String, chatId: String,
msg: GroupChatMessage): BbbCommonEnvCoreMsg = {
val envelope = makeEnvelope(MessageTypes.BROADCAST_TO_MEETING, GroupChatMessageBroadcastEvtMsg.NAME, meetingId, userId)
val header = makeHeader(GroupChatMessageBroadcastEvtMsg.NAME, meetingId, userId)
val cmsgs = GroupChatApp.toMessageToUser(msg)
val body = GroupChatMessageBroadcastEvtMsgBody(chatId, cmsgs)
val event = GroupChatMessageBroadcastEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
GroupChatApp.findGroupChatUser(msg.header.userId, liveMeeting.users2x) match {
case Some(s) => log.debug("Found sender")
case None => log.debug("NOT FOUND sender")
}
state.groupChats.find(msg.body.chatId) match {
case Some(c) => log.debug("FOUND CHAT ID " + c.id)
case None => log.debug("NOT FOUND CHAT ID " + msg.body.chatId)
}
state.groupChats.chats.values.toVector foreach { ch =>
log.debug("CHAT = " + ch.id)
}
val newState = for {
sender <- GroupChatApp.findGroupChatUser(msg.header.userId, liveMeeting.users2x)
chat <- state.groupChats.find(msg.body.chatId)
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId)
groupChat <- state.groupChats.find(msg.body.chatId)
} yield {
val gcm = GroupChatApp.toGroupChatMessage(sender, msg.body.msg)
val gcs = GroupChatApp.addGroupChatMessage(chat, state.groupChats, gcm)
val event = buildGroupChatMessageBroadcastEvtMsg(
liveMeeting.props.meetingProp.intId,
msg.header.userId, msg.body.chatId, gcm
)
bus.outGW.send(event)
state.update(gcs)
if (user.role != Roles.MODERATOR_ROLE && user.locked) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
if (groupChat.access == GroupChatAccess.PRIVATE) {
chatLocked = permissions.disablePrivChat
} else {
chatLocked = permissions.disablePubChat
}
}
}
newState match {
case Some(ns) => ns
case None => state
}
if (applyPermissionCheck && chatLocked) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to send a message to this group chat."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {
def makeHeader(name: String, meetingId: String, userId: String): BbbClientMsgHeader = {
BbbClientMsgHeader(name, meetingId, userId)
}
def makeEnvelope(msgType: String, name: String, meetingId: String, userId: String): BbbCoreEnvelope = {
val routing = Routing.addMsgToClientRouting(msgType, meetingId, userId)
BbbCoreEnvelope(name, routing)
}
def buildGroupChatMessageBroadcastEvtMsg(meetingId: String, userId: String, chatId: String,
msg: GroupChatMessage): BbbCommonEnvCoreMsg = {
val envelope = makeEnvelope(MessageTypes.BROADCAST_TO_MEETING, GroupChatMessageBroadcastEvtMsg.NAME, meetingId, userId)
val header = makeHeader(GroupChatMessageBroadcastEvtMsg.NAME, meetingId, userId)
val cmsgs = GroupChatApp.toMessageToUser(msg)
val body = GroupChatMessageBroadcastEvtMsgBody(chatId, cmsgs)
val event = GroupChatMessageBroadcastEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
GroupChatApp.findGroupChatUser(msg.header.userId, liveMeeting.users2x) match {
case Some(s) => log.debug("Found sender")
case None => log.debug("NOT FOUND sender")
}
state.groupChats.find(msg.body.chatId) match {
case Some(c) => log.debug("FOUND CHAT ID " + c.id)
case None => log.debug("NOT FOUND CHAT ID " + msg.body.chatId)
}
state.groupChats.chats.values.toVector foreach { ch =>
log.debug("CHAT = " + ch.id)
}
val newState = for {
sender <- GroupChatApp.findGroupChatUser(msg.header.userId, liveMeeting.users2x)
chat <- state.groupChats.find(msg.body.chatId)
} yield {
val gcm = GroupChatApp.toGroupChatMessage(sender, msg.body.msg)
val gcs = GroupChatApp.addGroupChatMessage(chat, state.groupChats, gcm)
val event = buildGroupChatMessageBroadcastEvtMsg(
liveMeeting.props.meetingProp.intId,
msg.header.userId, msg.body.chatId, gcm
)
bus.outGW.send(event)
state.update(gcs)
}
newState match {
case Some(ns) => ns
case None => state
}
}
}
}

View File

@ -4,8 +4,10 @@ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.models.Polls
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.SystemConfiguration
import org.bigbluebutton.core.apps.PermissionCheck
trait HidePollResultReqMsgHdlr {
trait HidePollResultReqMsgHdlr extends SystemConfiguration {
this: PollApp2x =>
def handle(msg: HidePollResultReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -21,10 +23,16 @@ trait HidePollResultReqMsgHdlr {
bus.outGW.send(msgEvent)
}
for {
hiddenPollId <- Polls.handleHidePollResultReqMsg(msg.header.userId, msg.body.pollId, liveMeeting)
} yield {
broadcastEvent(msg, hiddenPollId)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to hide poll result."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
for {
hiddenPollId <- Polls.handleHidePollResultReqMsg(msg.header.userId, msg.body.pollId, liveMeeting)
} yield {
broadcastEvent(msg, hiddenPollId)
}
}
}
}

View File

@ -6,8 +6,10 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.Polls
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait ShowPollResultReqMsgHdlr {
trait ShowPollResultReqMsgHdlr extends SystemConfiguration {
this: PollApp2x =>
def handle(msg: ShowPollResultReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -34,11 +36,16 @@ trait ShowPollResultReqMsgHdlr {
bus.outGW.send(annotationMsgEvent)
}
for {
(result, annotationProp) <- Polls.handleShowPollResultReqMsg(state, msg.header.userId, msg.body.pollId, liveMeeting)
} yield {
broadcastEvent(msg, result, annotationProp)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to show poll results."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
for {
(result, annotationProp) <- Polls.handleShowPollResultReqMsg(state, msg.header.userId, msg.body.pollId, liveMeeting)
} yield {
broadcastEvent(msg, result, annotationProp)
}
}
}
}

View File

@ -6,8 +6,10 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.Polls
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait StartCustomPollReqMsgHdlr {
trait StartCustomPollReqMsgHdlr extends SystemConfiguration {
this: PollApp2x =>
def handle(msg: StartCustomPollReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -22,10 +24,16 @@ trait StartCustomPollReqMsgHdlr {
bus.outGW.send(msgEvent)
}
for {
pvo <- Polls.handleStartCustomPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, msg.body.answers, liveMeeting)
} yield {
broadcastEvent(msg, pvo)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to start custom poll."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
for {
pvo <- Polls.handleStartCustomPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, msg.body.answers, liveMeeting)
} yield {
broadcastEvent(msg, pvo)
}
}
}
}

View File

@ -6,8 +6,10 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.Polls
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait StartPollReqMsgHdlr {
trait StartPollReqMsgHdlr extends SystemConfiguration {
this: PollApp2x =>
def handle(msg: StartPollReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -23,10 +25,16 @@ trait StartPollReqMsgHdlr {
bus.outGW.send(msgEvent)
}
for {
pvo <- Polls.handleStartPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, liveMeeting)
} yield {
broadcastEvent(msg, pvo)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to start poll."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
for {
pvo <- Polls.handleStartPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, liveMeeting)
} yield {
broadcastEvent(msg, pvo)
}
}
}
}

View File

@ -5,8 +5,10 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.Polls
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait StopPollReqMsgHdlr {
trait StopPollReqMsgHdlr extends SystemConfiguration {
this: PollApp2x =>
def broadcastPollStoppedEvtMsg(requesterId: String, stoppedPollId: String, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -21,7 +23,13 @@ trait StopPollReqMsgHdlr {
}
def handle(msg: StopPollReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
stopPoll(state, msg.header.userId, liveMeeting, bus)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to stop poll."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
stopPoll(state, msg.header.userId, liveMeeting, bus)
}
}
def stopPoll(state: MeetingState2x, requesterId: String, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {

View File

@ -14,9 +14,12 @@ trait CreateNewPresentationPodPubMsgHdlr extends SystemConfiguration {
def handle(msg: CreateNewPresentationPodPubMsg, state: MeetingState2x,
liveMeeting: LiveMeeting, bus: MessageBus): MeetingState2x = {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
if (applyPermissionCheck && !PermissionCheck.isAllowed(
PermissionCheck.MOD_LEVEL,
PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId
)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to eject user from meeting."
val reason = "No permission to create new presentation pod."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {

View File

@ -5,6 +5,7 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
trait PresentationUploadTokenReqMsgHdlr {
this: PresentationPodHdlrs =>
@ -64,12 +65,18 @@ trait PresentationUploadTokenReqMsgHdlr {
log.info("handlePresentationUploadTokenReqMsg" + liveMeeting.props.meetingProp.intId +
" userId=" + msg.header.userId + " filename=" + msg.body.filename)
if (userIsAllowedToUploadInPod(msg.body.podId, msg.header.userId)) {
val token = PresentationPodsApp.generateToken(msg.body.podId, msg.header.userId)
broadcastPresentationUploadTokenPassResp(msg, token)
broadcastPresentationUploadTokenSysPubMsg(msg, token)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to request presentation upload token."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
broadcastPresentationUploadTokenFailResp(msg)
if (userIsAllowedToUploadInPod(msg.body.podId, msg.header.userId)) {
val token = PresentationPodsApp.generateToken(msg.body.podId, msg.header.userId)
broadcastPresentationUploadTokenPassResp(msg, token)
broadcastPresentationUploadTokenSysPubMsg(msg, token)
} else {
broadcastPresentationUploadTokenFailResp(msg)
}
}
state

View File

@ -14,7 +14,7 @@ trait RemovePresentationPubMsgHdlr {
liveMeeting: LiveMeeting, bus: MessageBus
): MeetingState2x = {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to remove presentation from meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)

View File

@ -5,6 +5,7 @@ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.PermissionCheck
trait ResizeAndMovePagePubMsgHdlr {
this: PresentationPodHdlrs =>
@ -30,28 +31,35 @@ trait ResizeAndMovePagePubMsgHdlr {
bus.outGW.send(msgEvent)
}
val podId: String = msg.body.podId
val presentationId: String = msg.body.presentationId
val pageId: String = msg.body.pageId
val xOffset: Double = msg.body.xOffset
val yOffset: Double = msg.body.yOffset
val widthRatio: Double = msg.body.widthRatio
val heightRatio: Double = msg.body.heightRatio
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to resize and move page."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {
val podId: String = msg.body.podId
val presentationId: String = msg.body.presentationId
val pageId: String = msg.body.pageId
val xOffset: Double = msg.body.xOffset
val yOffset: Double = msg.body.yOffset
val widthRatio: Double = msg.body.widthRatio
val heightRatio: Double = msg.body.heightRatio
val newState = for {
pod <- PresentationPodsApp.getPresentationPod(state, podId)
(updatedPod, page) <- pod.resizePage(presentationId, pageId,
xOffset, yOffset, widthRatio, heightRatio)
} yield {
broadcastEvent(msg, podId, page)
val newState = for {
pod <- PresentationPodsApp.getPresentationPod(state, podId)
(updatedPod, page) <- pod.resizePage(presentationId, pageId,
xOffset, yOffset, widthRatio, heightRatio)
} yield {
broadcastEvent(msg, podId, page)
val pods = state.presentationPodManager.addPod(updatedPod)
state.update(pods)
}
val pods = state.presentationPodManager.addPod(updatedPod)
state.update(pods)
}
newState match {
case Some(ns) => ns
case None => state
newState match {
case Some(ns) => ns
case None => state
}
}
}
}

View File

@ -18,7 +18,7 @@ trait SetCurrentPagePubMsgHdlr {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to set presentation page."
val reason = "No permission to set current presentation page."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {

View File

@ -16,7 +16,7 @@ trait SetCurrentPresentationPubMsgHdlr {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to set presentation page."
val reason = "No permission to change current presentation."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {

View File

@ -17,7 +17,7 @@ trait SetPresenterInPodReqMsgHdlr {
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to set presenter in presentation."
val reason = "No permission to set presenter in presentation pod."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
state
} else {

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.sharednotes
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait ClearSharedNotePubMsgHdlr {
trait ClearSharedNotePubMsgHdlr extends SystemConfiguration {
this: SharedNotesApp2x =>
def handle(msg: ClearSharedNotePubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,9 +22,15 @@ trait ClearSharedNotePubMsgHdlr {
bus.outGW.send(msgEvent)
}
liveMeeting.notesModel.clearNote(msg.body.noteId) match {
case Some(noteReport) => broadcastEvent(msg, noteReport)
case None => log.warning("Could not find note " + msg.body.noteId)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to clear shared notes in meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
liveMeeting.notesModel.clearNote(msg.body.noteId) match {
case Some(noteReport) => broadcastEvent(msg, noteReport)
case None => log.warning("Could not find note " + msg.body.noteId)
}
}
}
}

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.sharednotes
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait CreateSharedNoteReqMsgHdlr {
trait CreateSharedNoteReqMsgHdlr extends SystemConfiguration {
this: SharedNotesApp2x =>
def handle(msg: CreateSharedNoteReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,9 +22,15 @@ trait CreateSharedNoteReqMsgHdlr {
bus.outGW.send(msgEvent)
}
if (!liveMeeting.notesModel.isNotesLimit) {
val (noteId, isNotesLimit) = liveMeeting.notesModel.createNote(msg.body.noteName)
broadcastEvent(msg, noteId, isNotesLimit)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to create new shared note."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
if (!liveMeeting.notesModel.isNotesLimit) {
val (noteId, isNotesLimit) = liveMeeting.notesModel.createNote(msg.body.noteName)
broadcastEvent(msg, noteId, isNotesLimit)
}
}
}
}

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.sharednotes
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait DestroySharedNoteReqMsgHdlr {
trait DestroySharedNoteReqMsgHdlr extends SystemConfiguration {
this: SharedNotesApp2x =>
def handle(msg: DestroySharedNoteReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,7 +22,13 @@ trait DestroySharedNoteReqMsgHdlr {
bus.outGW.send(msgEvent)
}
val isNotesLimit = liveMeeting.notesModel.destroyNote(msg.body.noteId)
broadcastEvent(msg, isNotesLimit)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to destory shared note."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
val isNotesLimit = liveMeeting.notesModel.destroyNote(msg.body.noteId)
broadcastEvent(msg, isNotesLimit)
}
}
}

View File

@ -24,7 +24,7 @@ trait MuteUserCmdMsgHdlrPermCheck extends MuteUserCmdMsgHdlrDefault with SystemC
val isAllowed = PermissionCheck.isAllowed(
PermissionCheck.MOD_LEVEL,
PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId
PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId
)
if (msg.header.userId != msg.body.userId && applyPermissionCheck && !isAllowed) {

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.whiteboard
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait ClearWhiteboardPubMsgHdlr {
trait ClearWhiteboardPubMsgHdlr extends SystemConfiguration {
this: WhiteboardApp2x =>
def handle(msg: ClearWhiteboardPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,10 +22,16 @@ trait ClearWhiteboardPubMsgHdlr {
bus.outGW.send(msgEvent)
}
for {
fullClear <- clearWhiteboard(msg.body.whiteboardId, msg.header.userId, liveMeeting)
} yield {
broadcastEvent(msg, fullClear)
if (!getWhiteboardAccess(liveMeeting) && applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to clear the whiteboard."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
for {
fullClear <- clearWhiteboard(msg.body.whiteboardId, msg.header.userId, liveMeeting)
} yield {
broadcastEvent(msg, fullClear)
}
}
}
}

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.whiteboard
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait ModifyWhiteboardAccessPubMsgHdlr {
trait ModifyWhiteboardAccessPubMsgHdlr extends SystemConfiguration {
this: WhiteboardApp2x =>
def handle(msg: ModifyWhiteboardAccessPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,7 +22,13 @@ trait ModifyWhiteboardAccessPubMsgHdlr {
bus.outGW.send(msgEvent)
}
modifyWhiteboardAccess(msg.body.multiUser, liveMeeting)
broadcastEvent(msg)
if (!getWhiteboardAccess(liveMeeting) && applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to modify access to the whiteboard."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
modifyWhiteboardAccess(msg.body.multiUser, liveMeeting)
broadcastEvent(msg)
}
}
}

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.whiteboard
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.SystemConfiguration
import org.bigbluebutton.core.apps.PermissionCheck
trait SendCursorPositionPubMsgHdlr {
trait SendCursorPositionPubMsgHdlr extends SystemConfiguration {
this: WhiteboardApp2x =>
def handle(msg: SendCursorPositionPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,6 +22,12 @@ trait SendCursorPositionPubMsgHdlr {
bus.outGW.send(msgEvent)
}
broadcastEvent(msg)
if (!getWhiteboardAccess(liveMeeting) && applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to send your cursor position."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
broadcastEvent(msg)
}
}
}

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.whiteboard
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait SendWhiteboardAnnotationPubMsgHdlr {
trait SendWhiteboardAnnotationPubMsgHdlr extends SystemConfiguration {
this: WhiteboardApp2x =>
def handle(msg: SendWhiteboardAnnotationPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,7 +22,13 @@ trait SendWhiteboardAnnotationPubMsgHdlr {
bus.outGW.send(msgEvent)
}
val annotation = sendWhiteboardAnnotation(msg.body.annotation, liveMeeting)
broadcastEvent(msg, annotation)
if (!getWhiteboardAccess(liveMeeting) && applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to send a whiteboard annotation."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
val annotation = sendWhiteboardAnnotation(msg.body.annotation, liveMeeting)
broadcastEvent(msg, annotation)
}
}
}

View File

@ -3,8 +3,10 @@ package org.bigbluebutton.core.apps.whiteboard
import org.bigbluebutton.core.running.{ LiveMeeting }
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.SystemConfiguration
trait UndoWhiteboardPubMsgHdlr {
trait UndoWhiteboardPubMsgHdlr extends SystemConfiguration {
this: WhiteboardApp2x =>
def handle(msg: UndoWhiteboardPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
@ -20,10 +22,16 @@ trait UndoWhiteboardPubMsgHdlr {
bus.outGW.send(msgEvent)
}
for {
lastAnnotation <- undoWhiteboard(msg.body.whiteboardId, msg.header.userId, liveMeeting)
} yield {
broadcastEvent(msg, lastAnnotation.id)
if (!getWhiteboardAccess(liveMeeting) && applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to undo an annotation."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW)
} else {
for {
lastAnnotation <- undoWhiteboard(msg.body.whiteboardId, msg.header.userId, liveMeeting)
} yield {
broadcastEvent(msg, lastAnnotation.id)
}
}
}
}

View File

@ -144,11 +144,11 @@ class MeetingActor(
// Create a default publish group chat
state = GroupChatApp.createDefaultPublicGroupChat(GroupChatApp.MAIN_PUBLIC_CHAT, state)
state = GroupChatApp.genTestChatMsgHistory(GroupChatApp.MAIN_PUBLIC_CHAT, state, BbbSystemConst.SYSTEM_USER, liveMeeting)
//state = GroupChatApp.genTestChatMsgHistory(GroupChatApp.MAIN_PUBLIC_CHAT, state, BbbSystemConst.SYSTEM_USER, liveMeeting)
// Create a default publish group chat
state = GroupChatApp.createDefaultPublicGroupChat("TEST_GROUP_CHAT", state)
state = GroupChatApp.genTestChatMsgHistory("TEST_GROUP_CHAT", state, BbbSystemConst.SYSTEM_USER, liveMeeting)
//state = GroupChatApp.createDefaultPublicGroupChat("TEST_GROUP_CHAT", state)
//state = GroupChatApp.genTestChatMsgHistory("TEST_GROUP_CHAT", state, BbbSystemConst.SYSTEM_USER, liveMeeting)
log.debug("NUM GROUP CHATS = " + state.groupChats.findAllPublicChats().length)

View File

@ -4,6 +4,7 @@ import org.bigbluebutton.common2.msgs.EjectUserFromVoiceCmdMsg
import org.bigbluebutton.core.models.VoiceUsers
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
import org.bigbluebutton.core2.message.senders.MsgBuilder
import org.bigbluebutton.core.apps.PermissionCheck
trait EjectUserFromVoiceCmdMsgHdlr {
this: MeetingActor =>
@ -13,12 +14,18 @@ trait EjectUserFromVoiceCmdMsgHdlr {
def handleEjectUserFromVoiceCmdMsg(msg: EjectUserFromVoiceCmdMsg) {
log.info("Received eject user request. meetingId=" + msg.header.meetingId + " userId=" + msg.body.userId)
for {
u <- VoiceUsers.findWithIntId(liveMeeting.voiceUsers, msg.body.userId)
} yield {
log.info("Ejecting user from voice. meetingId=" + props.meetingProp.intId + " userId=" + u.intId)
val event = MsgBuilder.buildEjectUserFromVoiceConfSysMsg(props.meetingProp.intId, props.voiceProp.voiceConf, u.voiceUserId)
outGW.send(event)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to eject the voice user."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
} else {
for {
u <- VoiceUsers.findWithIntId(liveMeeting.voiceUsers, msg.body.userId)
} yield {
log.info("Ejecting user from voice. meetingId=" + props.meetingProp.intId + " userId=" + u.intId)
val event = MsgBuilder.buildEjectUserFromVoiceConfSysMsg(props.meetingProp.intId, props.voiceProp.voiceConf, u.voiceUserId)
outGW.send(event)
}
}
}
}

View File

@ -4,6 +4,7 @@ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.models.{ UserState, Users2x, VoiceUserState, VoiceUsers }
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
import org.bigbluebutton.core2.MeetingStatus2x
import org.bigbluebutton.core.apps.PermissionCheck
trait MuteAllExceptPresentersCmdMsgHdlr {
this: MeetingActor =>
@ -11,28 +12,33 @@ trait MuteAllExceptPresentersCmdMsgHdlr {
val outGW: OutMsgRouter
def handleMuteAllExceptPresentersCmdMsg(msg: MuteAllExceptPresentersCmdMsg) {
if (MeetingStatus2x.isMeetingMuted(liveMeeting.status)) {
MeetingStatus2x.unmuteMeeting(liveMeeting.status)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to mute all except presenters."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
} else {
MeetingStatus2x.muteMeeting(liveMeeting.status)
}
if (MeetingStatus2x.isMeetingMuted(liveMeeting.status)) {
MeetingStatus2x.unmuteMeeting(liveMeeting.status)
} else {
MeetingStatus2x.muteMeeting(liveMeeting.status)
}
val muted = MeetingStatus2x.isMeetingMuted(liveMeeting.status)
val event = build(props.meetingProp.intId, msg.body.mutedBy, muted, msg.body.mutedBy)
val muted = MeetingStatus2x.isMeetingMuted(liveMeeting.status)
val event = build(props.meetingProp.intId, msg.body.mutedBy, muted, msg.body.mutedBy)
outGW.send(event)
outGW.send(event)
// I think the correct flow would be to find those who are presenters and exclude them
// from the list of voice users. The remaining, mute.
VoiceUsers.findAll(liveMeeting.voiceUsers) foreach { vu =>
if (!vu.listenOnly) {
Users2x.findWithIntId(liveMeeting.users2x, vu.intId) match {
case Some(u) => if (!u.presenter) muteUserInVoiceConf(vu, muted)
case None => muteUserInVoiceConf(vu, muted)
// I think the correct flow would be to find those who are presenters and exclude them
// from the list of voice users. The remaining, mute.
VoiceUsers.findAll(liveMeeting.voiceUsers) foreach { vu =>
if (!vu.listenOnly) {
Users2x.findWithIntId(liveMeeting.users2x, vu.intId) match {
case Some(u) => if (!u.presenter) muteUserInVoiceConf(vu, muted)
case None => muteUserInVoiceConf(vu, muted)
}
}
}
}
}
def usersWhoAreNotPresenter(): Vector[UserState] = {

View File

@ -19,7 +19,7 @@ trait MuteMeetingCmdMsgHdlrCheckPerm extends MuteMeetingCmdMsgHdlrDefault with S
override def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg): Unit = {
val isAllowed = PermissionCheck.isAllowed(
PermissionCheck.MOD_LEVEL,
PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId
PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId
)
if (applyPermissionCheck && !isAllowed) {

View File

@ -5,6 +5,7 @@ import org.bigbluebutton.core.apps.users.UsersApp
import org.bigbluebutton.core.models._
import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core2.message.senders.MsgBuilder
import org.bigbluebutton.core.apps.PermissionCheck
trait GuestsWaitingApprovedMsgHdlr extends HandlerHelpers {
this: BaseMeetingActor =>
@ -13,16 +14,22 @@ trait GuestsWaitingApprovedMsgHdlr extends HandlerHelpers {
val outGW: OutMsgRouter
def handleGuestsWaitingApprovedMsg(msg: GuestsWaitingApprovedMsg): Unit = {
msg.body.guests foreach { g =>
for {
// Remove guest from waiting list
_ <- GuestsWaiting.remove(liveMeeting.guestsWaiting, g.guest)
} yield {
UsersApp.approveOrRejectGuest(liveMeeting, outGW, g, msg.body.approvedBy)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to approve or deny guests in meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
} else {
msg.body.guests foreach { g =>
for {
// Remove guest from waiting list
_ <- GuestsWaiting.remove(liveMeeting.guestsWaiting, g.guest)
} yield {
UsersApp.approveOrRejectGuest(liveMeeting, outGW, g, msg.body.approvedBy)
}
}
}
notifyModeratorsOfGuestsApproval(msg.body.guests, msg.body.approvedBy)
notifyModeratorsOfGuestsApproval(msg.body.guests, msg.body.approvedBy)
}
}
def notifyModeratorsOfGuestsApproval(guests: Vector[GuestApprovedVO], approvedBy: String): Unit = {

View File

@ -2,24 +2,32 @@ package org.bigbluebutton.core2.message.handlers.guests
import org.bigbluebutton.common2.msgs.SetGuestPolicyCmdMsg
import org.bigbluebutton.core.models.{ GuestPolicy, GuestPolicyType, GuestsWaiting }
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core2.message.senders.{ MsgBuilder }
import org.bigbluebutton.core.apps.PermissionCheck
import org.bigbluebutton.core.running.MeetingActor
trait SetGuestPolicyMsgHdlr {
this: BaseMeetingActor =>
this: MeetingActor =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleSetGuestPolicyMsg(msg: SetGuestPolicyCmdMsg): Unit = {
val newPolicy = msg.body.policy.toUpperCase()
if (GuestPolicyType.policyTypes.contains(newPolicy)) {
val policy = GuestPolicy(newPolicy, msg.body.setBy)
GuestsWaiting.setGuestPolicy(liveMeeting.guestsWaiting, policy)
val event = MsgBuilder.buildGuestPolicyChangedEvtMsg(
liveMeeting.props.meetingProp.intId, msg.header.userId, newPolicy, msg.body.setBy
)
outGW.send(event)
if (applyPermissionCheck && !PermissionCheck.isAllowed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to set guest policy in meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW)
} else {
val newPolicy = msg.body.policy.toUpperCase()
if (GuestPolicyType.policyTypes.contains(newPolicy)) {
val policy = GuestPolicy(newPolicy, msg.body.setBy)
GuestsWaiting.setGuestPolicy(liveMeeting.guestsWaiting, policy)
val event = MsgBuilder.buildGuestPolicyChangedEvtMsg(
liveMeeting.props.meetingProp.intId, msg.header.userId, newPolicy, msg.body.setBy
)
outGW.send(event)
}
}
}

View File

@ -55,7 +55,7 @@ class ReceivedJsonMsgHdlrActor(val msgFromAkkaAppsEventBus: MsgFromAkkaAppsEvent
}
def handle(envelope: BbbCoreEnvelope, jsonNode: JsonNode): Unit = {
log.debug("*************** Route envelope name " + envelope.name)
//log.debug("*************** Route envelope name " + envelope.name)
envelope.name match {
case MeetingCreatedEvtMsg.NAME =>
route[MeetingCreatedEvtMsg](envelope, jsonNode)

View File

@ -227,7 +227,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function updateCopyrightText():void {
if (StringUtils.isEmpty(brandingOptions.copyright)) {
if (brandingOptions == null || StringUtils.isEmpty(brandingOptions.copyright)) {
copyrightText = ResourceUtil.getInstance().getString('bbb.mainshell.copyrightLabel2',[appVersion]);
} else {
copyrightText = String(brandingOptions.copyright).replace("{0}", appVersion);

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.chat.events
{
import flash.events.Event;
public class FocusOnChatBoxEvent extends Event
{
public static const FOCUS_ON_CHATBOX_EVENT:String = 'focus on chat box event';
public var chatId: String;
public function FocusOnChatBoxEvent(chatId:String)
{
super(FOCUS_ON_CHATBOX_EVENT, false, false);
this.chatId = chatId;
}
}
}

View File

@ -0,0 +1,19 @@
package org.bigbluebutton.modules.chat.events
{
import flash.events.Event;
public class GroupChatBoxClosedEvent extends Event
{
public static const CHATBOX_CLOSED_EVENT:String = 'group chat box closed event';
public var chatId: String;
public var windowId: String;
public function GroupChatBoxClosedEvent(chatId:String, windowId:String)
{
super(CHATBOX_CLOSED_EVENT, false, false);
this.chatId = chatId;
this.windowId = windowId;
}
}
}

View File

@ -1,31 +1,36 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.chat.events
{
import flash.events.Event;
public class OpenChatBoxEvent extends Event
{
public function OpenChatBoxEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
import flash.events.Event;
public class OpenChatBoxEvent extends Event
{
public static const OPEN_CHATBOX_EVENT:String = "open chat box event";
public var chatId: String;
public function OpenChatBoxEvent(chatId:String)
{
super(OPEN_CHATBOX_EVENT, false, false);
this.chatId = chatId;
}
}
}

View File

@ -35,7 +35,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.events.ChatToolbarButtonEvent;
import org.bigbluebutton.modules.chat.events.CreateGroupChatReqEvent;
import org.bigbluebutton.modules.chat.events.GetWelcomeMessageEvent;
import org.bigbluebutton.modules.chat.events.GroupChatBoxClosedEvent;
import org.bigbluebutton.modules.chat.events.GroupChatCreatedEvent;
import org.bigbluebutton.modules.chat.events.OpenChatBoxEvent;
import org.bigbluebutton.modules.chat.events.ReceivedGroupChatsEvent;
import org.bigbluebutton.modules.chat.events.SendGroupChatMessageEvent;
import org.bigbluebutton.modules.chat.events.SendPrivateChatMessageEvent;
@ -63,6 +65,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<MethodInvoker generator="{ChatMessageService}" method="handleReceivedGroupChatsEvent" />
</EventHandlers>
<EventHandlers type="{GroupChatBoxClosedEvent.CHATBOX_CLOSED_EVENT}">
<MethodInvoker generator="{ChatEventMapDelegate}" method="chatBoxClosed" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{GroupChatCreatedEvent.GROUP_CHAT_CREATED_EVENT}">
<MethodInvoker generator="{ChatEventMapDelegate}" method="createNewGroupChat" arguments="{event.chatId}"/>
</EventHandlers>
@ -71,6 +77,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<MethodInvoker generator="{ChatEventMapDelegate}" method="closeChatWindows" />
</EventHandlers>
<EventHandlers type="{OpenChatBoxEvent.OPEN_CHATBOX_EVENT}" >
<MethodInvoker generator="{ChatEventMapDelegate}" method="handleOpenChatBoxEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{EventConstants.SEND_PUBLIC_CHAT_REQ}">
<MethodInvoker generator="{ChatMessageService}" method="sendPublicMessageFromApi" arguments="{event.message}"/>
</EventHandlers>
@ -99,7 +110,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<EventHandlers type="{CreateGroupChatReqEvent.CREATE_GROUP_CHAT_REQ_EVENT}" >
<MethodInvoker generator="{ChatMessageService}" method="handleCreateGCReqEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{BBBEvent.RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT}" >
<EventAnnouncer generator="{ChatHistoryEvent}" type="{ChatHistoryEvent.REQUEST_HISTORY}"/>
</EventHandlers>

View File

@ -25,6 +25,9 @@ package org.bigbluebutton.modules.chat.maps {
import org.bigbluebutton.common.events.OpenWindowEvent;
import org.bigbluebutton.core.Options;
import org.bigbluebutton.core.model.LiveMeeting;
import org.bigbluebutton.modules.chat.events.FocusOnChatBoxEvent;
import org.bigbluebutton.modules.chat.events.GroupChatBoxClosedEvent;
import org.bigbluebutton.modules.chat.events.OpenChatBoxEvent;
import org.bigbluebutton.modules.chat.events.PrivateGroupChatCreatedEvent;
import org.bigbluebutton.modules.chat.model.ChatModel;
import org.bigbluebutton.modules.chat.model.ChatOptions;
@ -97,10 +100,22 @@ package org.bigbluebutton.modules.chat.maps {
}
}
private function findChatBoxMapper(chatId: String):GroupChatBoxMapper {
for (var i:int=0; i<_windowMapper.length; i++) {
var wMapper: GroupChatWindowMapper = _windowMapper[i];
var gBoxMapper: GroupChatBoxMapper = wMapper.findChatBoxMapper(chatId);
if (gBoxMapper != null) return gBoxMapper;
}
return null;
}
private function openChatBoxForPrivateChat(chatId: String, gc: GroupChat):void {
// Setup a tracker for the state of this chat.
var gcBoxMapper:GroupChatBoxMapper = new GroupChatBoxMapper(chatId);
gcBoxMapper.chatBoxOpen = true;
// By default we put all private chats on the main chat window. (ralam nov 5, 2017)
var winMapper:GroupChatWindowMapper = findGroupChatWindowMapper(MAIN_CHAT_WINID);
winMapper.addChatBox(gcBoxMapper);
@ -136,6 +151,22 @@ package org.bigbluebutton.modules.chat.maps {
}
}
public function handleOpenChatBoxEvent(event: OpenChatBoxEvent):void {
trace("######## handleOpenChatBoxEvent " + event.chatId + " ######");
var gc:GroupChat = LiveMeeting.inst().chats.getGroupChat(event.chatId);
if (gc != null && gc.access == GroupChat.PRIVATE) {
trace("######## FINDING BOX MAPPER FOR " + event.chatId + " ######");
var gboxMapper: GroupChatBoxMapper = findChatBoxMapper(event.chatId);
if (gboxMapper != null) {
trace("######## TODO: BOX MAPPER FOCUS ON " + event.chatId + " ######");
globalDispatcher.dispatchEvent(new FocusOnChatBoxEvent(event.chatId));
} else {
trace("######## BOX MAPPER OPENING ON " + event.chatId + " ######");
openChatBoxForPrivateChat(event.chatId, gc);
}
}
}
private function getChatOptions():void {
chatOptions = Options.getOptions(ChatOptions) as ChatOptions;
}
@ -148,6 +179,21 @@ package org.bigbluebutton.modules.chat.maps {
}
}
public function chatBoxClosed(event: GroupChatBoxClosedEvent):void {
trace("######## chatBoxClosed " + event.chatId + " ######");
var winMapper:GroupChatWindowMapper = findGroupChatWindowMapper(event.windowId);
if (winMapper != null) {
trace("######## chatBoxClosed winMapper " + winMapper.gcWinId + " ######");
var chatBox: GroupChatBoxMapper = winMapper.findChatBoxMapper(event.chatId);
if (chatBox != null) {
trace("********** CLOSING CHAT BOX " + event.chatId);
winMapper.removeChatBox(event.chatId);
} else {
trace("********** COULD NOT FIND CHAT BOX " + event.chatId);
}
}
}
private function openChatWindow(window:ChatWindow):void {
// Use the GLobal Dispatcher so that this message will be heard by the
// main application.

View File

@ -25,8 +25,8 @@ package org.bigbluebutton.modules.chat.maps
_chatBoxes.addItem(box);
}
public function removeChatBox(id: String):void { // never called
for (var i:int=0; i<_chatBoxes.length; i++) {
public function removeChatBox(id: String):void {
for (var i:int=0; i <_chatBoxes.length; i++) {
var box:GroupChatBoxMapper = _chatBoxes.getItemAt(i) as GroupChatBoxMapper;
if (box.chatBoxId == id) {
_chatBoxes.removeItemAt(i);
@ -34,6 +34,17 @@ package org.bigbluebutton.modules.chat.maps
}
}
public function findChatBoxMapper(id: String):GroupChatBoxMapper {
for (var i:int=0; i<_chatBoxes.length; i++) {
var box:GroupChatBoxMapper = _chatBoxes.getItemAt(i) as GroupChatBoxMapper;
if (box.chatBoxId == id) {
return box;
}
}
return null;
}
public function getNumChatBoxes():int {
return _chatBoxes.length;
}

View File

@ -1,35 +1,33 @@
package org.bigbluebutton.modules.chat.model
{
import com.asfusion.mate.events.Dispatcher;
import org.bigbluebutton.modules.chat.events.ConversationDeletedEvent;
import mx.collections.ArrayCollection;
import org.bigbluebutton.modules.chat.events.GroupChatCreatedEvent;
import org.bigbluebutton.modules.chat.events.ReceivedGroupChatsEvent;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
public class ChatModel
{
public static const MAIN_PUBLIC_CHAT:String = 'MAIN-PUBLIC-GROUP-CHAT';
private var convs:Object = new Object();
private var groupChats:Array = [];
private var groupChats:ArrayCollection = new ArrayCollection();
private var dispatcher:Dispatcher = new Dispatcher();
public function getGroupChat(id: String):GroupChat {
if (groupChats.hasOwnProperty(id)) {
return groupChats[id];
}
for (var i:int = 0; i < groupChats.length; i++) {
var gc: GroupChat = groupChats[i] as GroupChat;
if (gc.id == id) return gc;
}
return null;
}
public function getGroupChatIds():Array {
var gcIds: Array = new Array();
for (var id:String in groupChats) {
gcIds.push(id);
for (var i:int = 0; i < groupChats.length; i++) {
var gc: GroupChat = groupChats[i] as GroupChat;
gcIds.push(gc.id);
}
return gcIds;
}
@ -37,73 +35,47 @@ package org.bigbluebutton.modules.chat.model
public function addGroupChatsList(gcs: Array):void {
for (var i: int = 0; i < gcs.length; i++) {
var gc: GroupChat = gcs[i] as GroupChat;
groupChats[gc.id] = gc;
groupChats.addItem(gc);
}
dispatcher.dispatchEvent(new ReceivedGroupChatsEvent());
}
public function getChatConversation(convId:String):ChatConversation {
return null;
}
public function findChatWithUser(userId: String):GroupChat {
trace("######## NUM CHATS " + groupChats.length + " ######" );
for (var i: int = 0; i < groupChats.length; i++) {
var gc: GroupChat = groupChats[i] as GroupChat;
if (gc != null && gc.isChattingWith(userId)) {
trace("######## IS USER " + userId + " ###### IN " + gc.id);
return gc;
}
}
return null;
}
public function addGroupChat(gc: GroupChat):void {
groupChats[gc.id] = gc;
groupChats.addItem(gc);
dispatcher.dispatchEvent(new GroupChatCreatedEvent(gc.id));
}
private function getIndex(id: String):int {
for (var i:int = 0; i < groupChats.length; i++) {
var gc: GroupChat = groupChats[i] as GroupChat;
if (gc.id == id) return i;
}
return -1;
}
public function removeGroupChat(id: String):void {
if (groupChats.hasOwnProperty(id)) {
delete groupChats[id];
}
}
public static function getConvId(from:String, to: String):String {
var members:Array = new Array(to, from);
members.sort();
return members[0] + "-" + members[1];
}
public function newChatMessage(msg:ChatMessageVO):void {
var convId:String = getConvId(msg.fromUserId, msg.toUserId);
if (convs.hasOwnProperty(convId)) {
var cm1:ChatConversation = convs[convId] as ChatConversation;
cm1.newChatMessage(msg);
} else {
var cm2:ChatConversation = new ChatConversation(convId);
cm2.newChatMessage(msg);
convs[convId] = cm2;
for (var i:int = 0; i < groupChats.length; i++) {
var gc: GroupChat = groupChats[i] as GroupChat;
if (gc.id == id) groupChats.removeItemAt(i);
}
}
public function userLeft(userid:String):void {
for (var convId:String in convs){
if (convId.indexOf(userid) > 0) {
delete convs[convId];
dispatcher.dispatchEvent(new ConversationDeletedEvent(convId));
}
}
}
public function getChatConversation(convId:String):ChatConversation {
if (convs.hasOwnProperty(convId)) {
return convs[convId];
} else {
var conv: ChatConversation = new ChatConversation(convId);
convs[convId] = conv;
return conv;
}
}
public static function toChatMessage(rawMessage:Object):ChatMessageVO {
var msg:ChatMessageVO = new ChatMessageVO();
msg.fromUserId = rawMessage.fromUserId;
msg.fromUsername = rawMessage.fromUsername;
msg.fromColor = rawMessage.fromColor;
msg.fromTime = rawMessage.fromTime;
msg.fromTimezoneOffset = rawMessage.fromTimezoneOffset;
msg.toUserId = rawMessage.toUserId;
msg.toUsername = rawMessage.toUsername;
msg.message = rawMessage.message;
return msg;
}
}
}

View File

@ -28,7 +28,8 @@ package org.bigbluebutton.modules.chat.model
private var _dispatcher:Dispatcher = new Dispatcher();
public function GroupChat(id: String, name: String, access: String,
public function GroupChat(id: String,
name: String, access: String,
createdBy: GroupChatUser,
users: ArrayCollection,
msg: ArrayCollection) {
@ -43,11 +44,22 @@ package org.bigbluebutton.modules.chat.model
public function get id():String {
return _id;
}
public function get name(): String {
return _name;
}
public function isChattingWith(userId: String): Boolean {
for (var i:int = 0; i < _users.length; i++) {
var user:GroupChatUser = _users[i] as GroupChatUser;
trace("######## IS CHAT WITH USER? " + userId + " ###### GC USER=" + user.id);
if (user.id == userId) {
return true;
}
}
return false;
}
public function getNameAsUsers(exceptUserId:String):String {
if (users.length == 0) return _name;

View File

@ -18,6 +18,8 @@
*/
package org.bigbluebutton.modules.chat.services
{
import com.asfusion.mate.events.Dispatcher;
import flash.events.IEventDispatcher;
import flash.external.ExternalInterface;
@ -26,6 +28,7 @@ package org.bigbluebutton.modules.chat.services
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.model.LiveMeeting;
import org.bigbluebutton.modules.chat.events.CreateGroupChatReqEvent;
import org.bigbluebutton.modules.chat.events.OpenChatBoxEvent;
import org.bigbluebutton.modules.chat.events.SendGroupChatMessageEvent;
import org.bigbluebutton.modules.chat.model.GroupChat;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
@ -38,11 +41,10 @@ package org.bigbluebutton.modules.chat.services
public var sender:MessageSender;
public var receiver:MessageReceiver;
public var dispatcher:IEventDispatcher;
private var globalDispatcher:Dispatcher = new Dispatcher();
public function sendPublicMessageFromApi(event:SendGroupChatMessageEvent):void
{
//sendPublicMessage(event.chatId, msgVO);
}
@ -83,7 +85,25 @@ package org.bigbluebutton.modules.chat.services
}
public function handleCreateGCReqEvent(event:CreateGroupChatReqEvent):void {
sender.createGroupChat(event.name, event.access, event.users);
trace("######## REQUEST TO CREATE NEW GROUP CHAT ######");
// Right now we only support one-to-one private chats)
if (event.access == GroupChat.PRIVATE && event.users.length > 0) {
var chatWith: String = event.users[0] as String;
trace("######## PRIVATE CHAT WITH USER " + chatWith + " ######");
var gc: GroupChat = LiveMeeting.inst().chats.findChatWithUser(chatWith)
if (gc != null) {
// Already chatting with this user. Open the chat box.
trace("######## ALREADY CHATTING WITH USER " + chatWith + " ######");
globalDispatcher.dispatchEvent(new OpenChatBoxEvent(gc.id));
} else {
trace("######## NOT YET CHATTING WITH USER " + chatWith + " ######");
// Not chatting yet with this user.
sender.createGroupChat(event.name, event.access, event.users);
}
} else {
trace("######## PUBLIC CHAT ######");
sender.createGroupChat(event.name, event.access, event.users);
}
}
public function getGroupChats():void {

View File

@ -111,7 +111,8 @@ package org.bigbluebutton.modules.chat.services
var body: Object = msg.body as Object;
var corrId: String = body.correlationId as String;
var chatId: String = body.chatId as String;
var createdBy: GroupChatUser = new GroupChatUser(body.createdBy.id, body.createdBy.name);
var createdBy: GroupChatUser = new GroupChatUser(body.createdBy.id,
body.createdBy.name);
var name: String = body.name as String;
var access: String = body.access as String;
var users: Array = body.users as Array;

View File

@ -26,7 +26,6 @@ package org.bigbluebutton.modules.chat.services
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.managers.ConnectionManager;
import org.bigbluebutton.modules.chat.ChatUtil;
import org.bigbluebutton.modules.chat.model.ChatModel;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
import org.bigbluebutton.modules.chat.vo.GroupChatMsgFromUser;
import org.bigbluebutton.modules.chat.vo.GroupChatUser;

View File

@ -50,13 +50,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<fx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
import flash.events.TextEvent;
import mx.binding.utils.BindingUtils;
import flashx.textLayout.formats.Direction;
import org.as3commons.lang.StringUtils;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
@ -77,7 +73,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.events.GetWelcomeMessageEvent;
import org.bigbluebutton.modules.chat.events.PrivateChatMessageEvent;
import org.bigbluebutton.modules.chat.events.PublicChatMessageEvent;
import org.bigbluebutton.modules.chat.events.SendPrivateChatMessageEvent;
import org.bigbluebutton.modules.chat.events.SendGroupChatMessageEvent;
import org.bigbluebutton.modules.chat.model.ChatConversation;
import org.bigbluebutton.modules.chat.model.ChatModel;
@ -91,6 +86,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
public var chatWithUserID:String;
public var chatWithUsername:String
public var chatId: String = null;
public var parentWindowId:String = null;
public var publicChat: Boolean = false;
public var read:Boolean = true;
public var userHasLeft:Boolean = false;
@ -139,11 +135,13 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
scrollTimer = new Timer(750, 1);
scrollTimer.addEventListener(TimerEvent.TIMER, onScrollTimer);
// Initialize the indicator for the position in the message history, and add the listener for message history navigation
// Initialize the indicator for the position in the message history,
// and add the listener for message history navigation
currentMessage = -1;
latestMessage = -1;
ResourceUtil.getInstance().addEventListener(Event.CHANGE, localeChanged); // Listen for locale changing
// Listen for locale changing
ResourceUtil.getInstance().addEventListener(Event.CHANGE, localeChanged);
// Listen for the ENTER key to send the message.
txtMsgArea.addEventListener(TextEvent.TEXT_INPUT, handleTextInput);
@ -167,7 +165,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
// chatToolbar.registerListeners(chatMessagesList);
chatMessagesList.addEventListener(ChatEvent.RESIZE_CHAT_TOOLBAR, adjustToolbarWidthAccordingToScrollBar);
chatMessagesList.addEventListener(ChatEvent.RESIZE_CHAT_TOOLBAR,
adjustToolbarWidthAccordingToScrollBar);
}
@ -301,8 +300,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
msg.toUsername = SPACE;
msg.message = "<b><i>"+ResourceUtil.getInstance().getString('bbb.chat.private.userLeft')+"</b></i>";
var myChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(id);
myChat.newChatMessage(msg);
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
if (groupChat != null) {
groupChat.addMessage(msg);
}
}
private function displayUserHasJoinedMessage():void {
@ -316,8 +317,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
msg.toUsername = SPACE;
msg.message = "<b><i>"+ResourceUtil.getInstance().getString('bbb.chat.private.userJoined')+"</b></i>";
var myChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(id);
myChat.newChatMessage(msg);
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
if (groupChat != null) {
groupChat.addMessage(msg);
}
}
public function focusToTextMessageArea():void {
@ -326,7 +329,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function handlePublicChatMessageEvent(event:PublicChatMessageEvent):void {
if (chatId == event.chatId) {
if (chatId == event.chatId && chatMessages != null) {
chatMessages.newChatMessage(event.msg);
scrollToEndOfMessage();
}
@ -376,8 +379,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
msg.toUsername = SPACE;
msg.message = "<b><i>"+ResourceUtil.getInstance().getString('bbb.chat.private.closeMessage', [keyCombo])+"</b></i>";
var myChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(id);
myChat.newChatMessage(msg);
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
if (groupChat != null) {
groupChat.addMessage(msg);
}
}
public function scrollToEndOfMessage():void {
@ -423,12 +428,14 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function copyAllText():void{
var myChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(id);
System.setClipboard(myChat.getAllMessageAsString());
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
if (groupChat != null) {
System.setClipboard(groupChat.getAllMessageAsString());
}
}
public function getChatId():String {
return id;
return chatId;
}
private function addContextMenuItems():void {
@ -444,8 +451,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private function menuItemHandler(e:ContextMenuEvent):void{
if (e.target.caption == ResourceUtil.getInstance().getString("bbb.chat.contextmenu.copyalltext")){
var myChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(id);
System.setClipboard(myChat.getAllMessageAsString());
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
if (groupChat != null) {
System.setClipboard(groupChat.getAllMessageAsString());
}
}
}
@ -513,30 +522,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
globalDispatcher.dispatchEvent(publicEvent);
}
}
private function sendPrivateChatMessage(message:String):void {
var privateEvent:SendPrivateChatMessageEvent = new SendPrivateChatMessageEvent(SendPrivateChatMessageEvent.SEND_PRIVATE_CHAT_MESSAGE_EVENT);
var cm:ChatMessageVO = new ChatMessageVO();
cm.fromUserId = UsersUtil.getMyUserID();
cm.fromUsername = UsersUtil.getMyUsername();
// get the color value from ColorPicker
cm.fromColor = cmpColorPicker.selectedColor.toString();
// Get the current UTC time and the timezone for this sender.
// The receiver will have to convert this to local time.
var now:Date = new Date();
cm.fromTime = now.valueOf();
cm.fromTimezoneOffset = now.getTimezoneOffset();
//cm.message = ChatUtil.parseURLs(ChatUtil.cleanup(message));
cm.message = ExternalInterface.call('parseURLs', (ChatUtil.cleanup(message)));
cm.toUserId = chatWithUserID;
cm.toUsername = chatWithUsername;
privateEvent.chatMessage = cm;
globalDispatcher.dispatchEvent(privateEvent);
}
private function handleTextInput(e:TextEvent):void {
if ((e.text.length == 1) && (e.text.charCodeAt(0) == 10) /*ENTER-KEY*/ && messageCanBeSent) {
sendMessages();
@ -636,12 +622,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function handleClearPublicChatBoxMessages(event:ClearPublicChatEvent):void {
//if(publicChat){
var myChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(id);
myChat.clearPublicChat();
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
if (groupChat != null) {
groupChat.clearPublicChat();
invalidateDisplayList();
validateNow();
// }
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {

View File

@ -37,7 +37,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mate:Listener type="{ShortcutEvent.FOCUS_CHAT_TABS}" method="focusChatTabs" />
<mate:Listener type="{ChatToolbarButtonEvent.SAVE_CHAT_TOOLBAR_EVENT}" method="dispatchSaveChatEvent" />
<mate:Listener type="{ChatToolbarButtonEvent.COPY_CHAT_TOOLBAR_EVENT}" method="dispatchCopyChatEvent" />
<mate:Listener type="{ShortcutEvent.CLOSE_PRIVATE}" method="remoteClosePrivate" />
<mate:Listener type="{ShortcutEvent.CLOSE_PRIVATE}" method="remoteClosePrivate" />
<mate:Listener type="{FocusOnChatBoxEvent.FOCUS_ON_CHATBOX_EVENT}" method="handleFocusOnChatBoxEvent" />
</fx:Declarations>
<fx:Script>
@ -64,6 +66,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.events.ChatNoiseEnabledEvent;
import org.bigbluebutton.modules.chat.events.ChatSaveEvent;
import org.bigbluebutton.modules.chat.events.ChatToolbarButtonEvent;
import org.bigbluebutton.modules.chat.events.FocusOnChatBoxEvent;
import org.bigbluebutton.modules.chat.events.GroupChatBoxClosedEvent;
import org.bigbluebutton.modules.chat.events.PrivateChatMessageEvent;
import org.bigbluebutton.modules.chat.events.PrivateGroupChatCreatedEvent;
import org.bigbluebutton.modules.chat.events.PublicChatMessageEvent;
@ -82,8 +86,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private var globalDispatcher:Dispatcher = new Dispatcher();
[Bindable] public var chatOptions:ChatOptions;
public var mainChatId: String;
[Bindable] public var mainChatId: String;
public var openTabBox:Boolean = false;
[Bindable] public var windowId:String = ""
private static const PUBLIC_TAB_NEW:String = ResourceUtil.getInstance().getString("bbb.accessibility.chat.chatView.publicTabNew");
private var publicWaiting:Boolean = false;
@ -330,6 +335,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
chatBox.name = groupChatId;
chatBox.chatWithUserID = groupChatId;
chatBox.parentWindowId = windowId;
chatBox.tabIndexer.startIndex = tabIndexer.startIndex + 10;
if (publicChat) {
@ -427,11 +433,26 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function onTabClose(e:SuperTabEvent):void{
trace("########onTabClose REQUEST TO CLOSE CHAT BOX ###### " + e.type);
trace("########onTabClose CLOSE CHAT BOX ######");
var chatBox:ChatBox = chatTabs.getChildAt(e.tabIndex) as ChatBox;
trace("########onTabClose CLOSE CHAT BOX ###### winId="
+ chatBox.parentWindowId + " chatId=" + chatBox.chatId);
dispatchEvent(e);
}
private function onUserClosedTab(e:SuperTabEvent):void{
var name:String = chatTabs.getChildAt(e.tabIndex).name;
trace("######## CLOSE CHAT BOX ######");
var chatBox:ChatBox = chatTabs.getChildAt(e.tabIndex) as ChatBox;
trace("######## CLOSE CHAT BOX ###### winId="
+ chatBox.parentWindowId + " chatId=" + chatBox.chatId);
globalDispatcher.dispatchEvent(new GroupChatBoxClosedEvent(chatBox.chatId,
chatBox.parentWindowId));
}
private function handleFocusOnChatBoxEvent(e:FocusOnChatBoxEvent):void {
trace("######## TODO: handleFocusOnChatBoxEvent CHAT BOX ###### chatId="
+ e.chatId);
}
private function remoteClosePrivate(e:ShortcutEvent):void {

View File

@ -60,7 +60,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private var disp:Dispatcher = new Dispatcher();
[Bindable] public var chatOptions:ChatOptions;
private var _windowId: String;
[Bindable] private var _windowId: String;
// The chatId that would be displayed when this window opens.
[Bindable] private var _mainChatId:String;
@ -218,6 +218,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mx:Button id="createGCBtn" label="Create" height="20" click="onCreateGCBtnClick()"
includeInLayout="{_mainChatId == ChatModel.MAIN_PUBLIC_CHAT}"/>
<views:ChatView id="chatView" chatOptions="{chatOptions}" mainChatId="{_mainChatId}"
windowId="{_windowId}"
openTabBox="{_openAddTabBox}" includeInLayout="true"/>
</mx:VBox>

View File

@ -65,7 +65,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
public function refreshRole(amIModerator:Boolean):void {
this.amIModerator = amIModerator;
visible = includeInLayout = enabled = amIModerator;
if (!layoutMenu && layoutMenu.visible) {
if (layoutMenu != null && layoutMenu.visible) {
layoutMenu.hide();
}
}

View File

@ -1,12 +1,15 @@
package org.bigbluebutton.modules.polling.service
{
import com.asfusion.mate.events.Dispatcher;
import flash.accessibility.Accessibility;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.core.model.LiveMeeting;
import org.bigbluebutton.modules.chat.model.ChatConversation;
import org.bigbluebutton.modules.chat.model.ChatModel;
import org.bigbluebutton.modules.chat.model.GroupChat;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
import org.bigbluebutton.modules.polling.events.PollShowResultEvent;
import org.bigbluebutton.modules.polling.events.PollStartedEvent;
@ -93,9 +96,10 @@ package org.bigbluebutton.modules.polling.service
pollResultMessage.toUsername = ResourceUtil.getInstance().getString("bbb.chat.chatMessage.systemMessage");
pollResultMessage.message = accessibleAnswers;
var pubChat: ChatConversation = LiveMeeting.inst().chats.getChatConversation(ChatModel.MAIN_PUBLIC_CHAT);
pubChat.newChatMessage(pollResultMessage);
var groupChat: GroupChat = LiveMeeting.inst().chats.getGroupChat(ChatModel.MAIN_PUBLIC_CHAT);
if (groupChat != null) {
groupChat.addMessage(pollResultMessage);
}
}
}