Merge pull request #4534 from ritzalam/implement-multi-chat
Implement multi chat and multi-presentation
This commit is contained in:
commit
40fbc78194
@ -79,3 +79,7 @@ services {
|
||||
telizeHost = "www.telize.com"
|
||||
telizePort = 80
|
||||
}
|
||||
|
||||
apps {
|
||||
checkPermissions = true
|
||||
}
|
@ -59,4 +59,6 @@ trait SystemConfiguration {
|
||||
lazy val httpPort = Try(config.getInt("http.port")).getOrElse(9090)
|
||||
lazy val telizeHost = Try(config.getString("services.telizeHost")).getOrElse("")
|
||||
lazy val telizePort = Try(config.getInt("services.telizePort")).getOrElse(80)
|
||||
|
||||
lazy val applyPermissionCheck = Try(config.getBoolean("apps.checkPermissions")).getOrElse(false)
|
||||
}
|
||||
|
@ -1,10 +1,63 @@
|
||||
package org.bigbluebutton.core.apps
|
||||
|
||||
import org.bigbluebutton.common2.domain.UserVO
|
||||
import org.bigbluebutton.core.models.{ Roles, UserState, Users2x }
|
||||
import org.bigbluebutton.core.running.OutMsgRouter
|
||||
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender }
|
||||
|
||||
trait PermisssionCheck {
|
||||
object PermisssionCheck {
|
||||
|
||||
def isAllowed(permission: String, role: String, user: UserVO): Boolean = {
|
||||
true
|
||||
val MOD_LEVEL = 100
|
||||
val AUTHED_LEVEL = 50
|
||||
val GUEST_LEVEL = 0
|
||||
|
||||
val PRESENTER_LEVEL = 100
|
||||
val VIEWER_LEVEL = 0
|
||||
|
||||
private def permissionToLevel(user: UserState): Int = {
|
||||
if (user.role == Roles.MODERATOR_ROLE) {
|
||||
MOD_LEVEL
|
||||
} else if (user.authed) {
|
||||
AUTHED_LEVEL
|
||||
} else {
|
||||
GUEST_LEVEL
|
||||
}
|
||||
}
|
||||
|
||||
private def roleToLevel(user: UserState): Int = {
|
||||
if (user.presenter) PRESENTER_LEVEL else VIEWER_LEVEL
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will check if the user that issued the command has the correct permissions.
|
||||
*
|
||||
* Example of the permissions level are "AUTHENTICATED", "MODERATOR" and "GUEST". Example of roles
|
||||
* are "VIEWER" and "PRESENTER".
|
||||
*
|
||||
* @param permissionLevel Lowest permission needed to have access.
|
||||
* @param roleLevel Lowest role needed to have access.
|
||||
* @return true allows API to execute, false denies executing API
|
||||
*/
|
||||
def isAllowed(permissionLevel: Int, roleLevel: Int, users: Users2x, userId: String): Boolean = {
|
||||
Users2x.findWithIntId(users, userId) match {
|
||||
case Some(user) =>
|
||||
println("permissionToLevel = " + permissionToLevel(user) + " permissionLevel=" + permissionLevel)
|
||||
val permLevelCheck = permissionToLevel(user) >= permissionLevel
|
||||
println("roleToLevel = " + roleToLevel(user) + " roleLevel=" + roleLevel)
|
||||
val roleLevelCheck = roleToLevel(user) >= roleLevel
|
||||
|
||||
println("PERMLEVELCHECK = " + permLevelCheck + " ROLELEVELCHECK=" + roleLevelCheck)
|
||||
permLevelCheck && roleLevelCheck
|
||||
false
|
||||
case None => false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def ejectUserForFailedPermission(meetingId: String, userId: String, reason: String, outGW: OutMsgRouter): Unit = {
|
||||
val ejectedBy = "SYSTEM"
|
||||
|
||||
Sender.sendUserEjectedFromMeetingClientEvtMsg(meetingId, userId, ejectedBy, reason, outGW)
|
||||
// send a system message to force disconnection
|
||||
Sender.sendUserEjectedFromMeetingSystemMsg(meetingId, userId, ejectedBy, outGW)
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ import org.bigbluebutton.core.running.LiveMeeting
|
||||
|
||||
class PresentationApp2x(implicit val context: ActorContext)
|
||||
extends NewPresentationMsgHdlr
|
||||
// with SetCurrentPresentationPubMsgHdlr
|
||||
// with GetPresentationInfoReqMsgHdlr
|
||||
with SetCurrentPagePubMsgHdlr
|
||||
with ResizeAndMovePagePubMsgHdlr
|
||||
with RemovePresentationPubMsgHdlr
|
||||
@ -18,7 +16,6 @@ class PresentationApp2x(implicit val context: ActorContext)
|
||||
with PresentationConversionUpdatePubMsgHdlr
|
||||
with PresentationPageCountErrorPubMsgHdlr
|
||||
with PresentationPageGeneratedPubMsgHdlr
|
||||
with PresentationConversionCompletedPubMsgHdlr
|
||||
with SyncGetPresentationInfoRespMsgHdlr {
|
||||
|
||||
val log = Logging(context.system, getClass)
|
||||
|
@ -1,47 +0,0 @@
|
||||
package org.bigbluebutton.core.apps.presentation
|
||||
|
||||
import org.bigbluebutton.common2.domain.PageVO
|
||||
import org.bigbluebutton.common2.msgs._
|
||||
import org.bigbluebutton.core.apps.Presentation
|
||||
import org.bigbluebutton.core.bus.MessageBus
|
||||
import org.bigbluebutton.core.running.{ LiveMeeting }
|
||||
|
||||
trait PresentationConversionCompletedPubMsgHdlr {
|
||||
this: PresentationApp2x =>
|
||||
|
||||
def handle(
|
||||
msg: PresentationConversionCompletedSysPubMsg,
|
||||
liveMeeting: LiveMeeting, bus: MessageBus
|
||||
): Unit = {
|
||||
def broadcastEvent(msg: PresentationConversionCompletedSysPubMsg): Unit = {
|
||||
val routing = Routing.addMsgToClientRouting(
|
||||
MessageTypes.BROADCAST_TO_MEETING,
|
||||
liveMeeting.props.meetingProp.intId, msg.header.userId
|
||||
)
|
||||
val envelope = BbbCoreEnvelope(PresentationConversionCompletedEvtMsg.NAME, routing)
|
||||
val header = BbbClientMsgHeader(
|
||||
PresentationConversionCompletedEvtMsg.NAME,
|
||||
liveMeeting.props.meetingProp.intId, msg.header.userId
|
||||
)
|
||||
|
||||
val body = PresentationConversionCompletedEvtMsgBody(msg.body.podId, msg.body.messageKey, msg.body.code, msg.body.presentation)
|
||||
val event = PresentationConversionCompletedEvtMsg(header, body)
|
||||
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
|
||||
bus.outGW.send(msgEvent)
|
||||
}
|
||||
|
||||
val pages = new collection.mutable.HashMap[String, PageVO]
|
||||
|
||||
msg.body.presentation.pages.foreach { p =>
|
||||
val page = PageVO(p.id, p.num, p.thumbUri, p.swfUri, p.txtUri, p.svgUri, p.current, p.xOffset, p.yOffset,
|
||||
p.widthRatio, p.heightRatio)
|
||||
pages += page.id -> page
|
||||
}
|
||||
|
||||
val pres = new Presentation(msg.body.presentation.id, msg.body.presentation.name, msg.body.presentation.current,
|
||||
pages.toMap, msg.body.presentation.downloadable)
|
||||
|
||||
presentationConversionCompleted(liveMeeting, pres)
|
||||
broadcastEvent(msg)
|
||||
}
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
package org.bigbluebutton.core.apps.presentationpod
|
||||
|
||||
import org.bigbluebutton.common2.domain.{ PresentationPodVO, PresentationVO }
|
||||
|
@ -0,0 +1,63 @@
|
||||
package org.bigbluebutton.core.apps.presentationpod
|
||||
|
||||
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.common2.domain.{ PageVO, PresentationVO }
|
||||
import org.bigbluebutton.core.apps.Presentation
|
||||
|
||||
trait PresentationConversionCompletedSysPubMsgHdlr {
|
||||
|
||||
this: PresentationPodHdlrs =>
|
||||
|
||||
def handle(
|
||||
msg: PresentationConversionCompletedSysPubMsg, state: MeetingState2x,
|
||||
liveMeeting: LiveMeeting, bus: MessageBus
|
||||
): MeetingState2x = {
|
||||
|
||||
def broadcastPresentationConversionCompletedEvtMsg(podId: String, userId: String, messageKey: String,
|
||||
code: String, presentation: PresentationVO): Unit = {
|
||||
val routing = Routing.addMsgToClientRouting(
|
||||
MessageTypes.BROADCAST_TO_MEETING,
|
||||
liveMeeting.props.meetingProp.intId, userId
|
||||
)
|
||||
val envelope = BbbCoreEnvelope(PresentationConversionCompletedEvtMsg.NAME, routing)
|
||||
val header = BbbClientMsgHeader(PresentationConversionCompletedEvtMsg.NAME, liveMeeting.props.meetingProp.intId, userId)
|
||||
|
||||
val body = PresentationConversionCompletedEvtMsgBody(podId, messageKey, code, presentation)
|
||||
val event = PresentationConversionCompletedEvtMsg(header, body)
|
||||
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
|
||||
bus.outGW.send(msgEvent)
|
||||
}
|
||||
|
||||
val pages = new collection.mutable.HashMap[String, PageVO]
|
||||
|
||||
msg.body.presentation.pages.foreach { p =>
|
||||
val page = PageVO(p.id, p.num, p.thumbUri, p.swfUri, p.txtUri, p.svgUri, p.current, p.xOffset, p.yOffset,
|
||||
p.widthRatio, p.heightRatio)
|
||||
pages += page.id -> page
|
||||
}
|
||||
|
||||
val pres = new Presentation(msg.body.presentation.id, msg.body.presentation.name, msg.body.presentation.current,
|
||||
pages.toMap, msg.body.presentation.downloadable)
|
||||
val presVO = PresentationPodsApp.translatePresentationToPresentationVO(pres)
|
||||
val podId = msg.body.podId
|
||||
|
||||
val newState = for {
|
||||
pod <- PresentationPodsApp.getPresentationPod(state, podId)
|
||||
} yield {
|
||||
broadcastPresentationConversionCompletedEvtMsg(pod.id, msg.header.userId, msg.body.messageKey, msg.body.code, presVO)
|
||||
|
||||
val pods = state.presentationPodManager.addPresentationToPod(pod.id, pres)
|
||||
state.update(pods)
|
||||
}
|
||||
|
||||
newState match {
|
||||
case Some(ns) => ns
|
||||
case None => state
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.bigbluebutton.core.apps.presentationpod
|
||||
|
||||
//import org.bigbluebutton.core.apps.presentationpod._
|
||||
import akka.actor.ActorContext
|
||||
import akka.event.Logging
|
||||
|
||||
@ -9,6 +8,7 @@ class PresentationPodHdlrs(implicit val context: ActorContext)
|
||||
with GetPresentationInfoReqMsgHdlr
|
||||
with GetAllPresentationPodsReqMsgHdlr
|
||||
with SetCurrentPresentationPubMsgHdlr
|
||||
with PresentationConversionCompletedSysPubMsgHdlr
|
||||
with RemovePresentationPodPubMsgHdlr {
|
||||
|
||||
val log = Logging(context.system, getClass)
|
||||
|
@ -12,11 +12,6 @@ object PresentationPodsApp {
|
||||
PresentationPodFactory.create(ownerId)
|
||||
}
|
||||
|
||||
// def createPresentationPod(id: String, ownerId: String, currentPresenter: String, authorizedPresenters: Vector[String],
|
||||
// presentations: collection.immutable.Map[String, Presentation]): PresentationPod = {
|
||||
// PresentationPodFactory.create(ownerId)
|
||||
// }
|
||||
|
||||
def createDefaultPresentationPod(state: MeetingState2x): MeetingState2x = {
|
||||
val defaultPresPod = PresentationPodFactory.create("the-owner-id")
|
||||
val podManager = state.presentationPodManager.addPod(defaultPresPod)
|
||||
@ -52,5 +47,9 @@ object PresentationPodsApp {
|
||||
state.update(podManager)
|
||||
}
|
||||
|
||||
def translatePresentationToPresentationVO(pres: Presentation): PresentationVO = {
|
||||
PresentationVO(pres.id, pres.name, pres.current, pres.pages.values.toVector, pres.downloadable)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.bigbluebutton.core.apps.presentationpod
|
||||
|
||||
import org.bigbluebutton.common2.domain.PresentationPodVO
|
||||
import org.bigbluebutton.common2.msgs._
|
||||
import org.bigbluebutton.core.bus.MessageBus
|
||||
import org.bigbluebutton.core.domain.MeetingState2x
|
||||
|
@ -1,17 +1,45 @@
|
||||
package org.bigbluebutton.core.apps.users
|
||||
|
||||
import org.bigbluebutton.SystemConfiguration
|
||||
import org.bigbluebutton.common2.msgs._
|
||||
import org.bigbluebutton.core.api.Permissions
|
||||
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
||||
import org.bigbluebutton.core.apps.PermisssionCheck
|
||||
import org.bigbluebutton.core.running.{ OutMsgRouter }
|
||||
import org.bigbluebutton.core.running.MeetingActor
|
||||
import org.bigbluebutton.core2.MeetingStatus2x
|
||||
|
||||
trait ChangeLockSettingsInMeetingCmdMsgHdlr {
|
||||
trait ChangeLockSettingsInMeetingCmdMsgHdlrDefault {
|
||||
def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg): Unit = {}
|
||||
}
|
||||
|
||||
trait ChangeLockSettingsInMeetingCmdMsgHdlrCheckPerm
|
||||
extends ChangeLockSettingsInMeetingCmdMsgHdlrDefault with SystemConfiguration {
|
||||
this: MeetingActor =>
|
||||
|
||||
val outGW: OutMsgRouter
|
||||
|
||||
def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg): Unit = {
|
||||
override def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg): Unit = {
|
||||
val isAllowed = PermisssionCheck.isAllowed(
|
||||
PermisssionCheck.MOD_LEVEL,
|
||||
PermisssionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.body.setBy
|
||||
)
|
||||
|
||||
if (applyPermissionCheck && !isAllowed) {
|
||||
val meetingId = liveMeeting.props.meetingProp.intId
|
||||
val reason = "No permission to change lock settings"
|
||||
PermisssionCheck.ejectUserForFailedPermission(meetingId, msg.body.setBy, reason, outGW)
|
||||
} else {
|
||||
super.handleSetLockSettings(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ChangeLockSettingsInMeetingCmdMsgHdlr extends ChangeLockSettingsInMeetingCmdMsgHdlrCheckPerm {
|
||||
this: MeetingActor =>
|
||||
|
||||
val outGW: OutMsgRouter
|
||||
|
||||
override def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg): Unit = {
|
||||
val settings = Permissions(
|
||||
disableCam = msg.body.disableCam,
|
||||
disableMic = msg.body.disableMic,
|
||||
|
@ -3,7 +3,7 @@ package org.bigbluebutton.core.apps.users
|
||||
import org.bigbluebutton.common2.msgs._
|
||||
import org.bigbluebutton.core.models._
|
||||
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
|
||||
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
||||
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender }
|
||||
|
||||
trait EjectUserFromMeetingCmdMsgHdlr {
|
||||
this: UsersApp =>
|
||||
@ -16,22 +16,22 @@ trait EjectUserFromMeetingCmdMsgHdlr {
|
||||
user <- Users2x.ejectFromMeeting(liveMeeting.users2x, msg.body.userId)
|
||||
} yield {
|
||||
RegisteredUsers.remove(msg.body.userId, liveMeeting.registeredUsers)
|
||||
|
||||
val reason = "user ejected by another user"
|
||||
// send a message to client
|
||||
val ejectFromMeetingClientEvent = MsgBuilder.buildUserEjectedFromMeetingEvtMsg(
|
||||
Sender.sendUserEjectedFromMeetingClientEvtMsg(
|
||||
liveMeeting.props.meetingProp.intId,
|
||||
user.intId, msg.body.ejectedBy
|
||||
user.intId, msg.body.ejectedBy, reason, outGW
|
||||
)
|
||||
outGW.send(ejectFromMeetingClientEvent)
|
||||
|
||||
log.info("Ejecting user from meeting (client msg). meetingId=" + liveMeeting.props.meetingProp.intId +
|
||||
" userId=" + msg.body.userId)
|
||||
|
||||
// send a system message to force disconnection
|
||||
val ejectFromMeetingSystemEvent = MsgBuilder.buildDisconnectClientSysMsg(
|
||||
Sender.sendUserEjectedFromMeetingSystemMsg(
|
||||
liveMeeting.props.meetingProp.intId,
|
||||
user.intId, "eject-user"
|
||||
user.intId, msg.body.ejectedBy, outGW
|
||||
)
|
||||
outGW.send(ejectFromMeetingSystemEvent)
|
||||
|
||||
log.info("Ejecting user from meeting (system msg). meetingId=" + liveMeeting.props.meetingProp.intId +
|
||||
" userId=" + msg.body.userId)
|
||||
|
||||
|
@ -1,23 +1,61 @@
|
||||
package org.bigbluebutton.core.apps.users
|
||||
|
||||
import org.bigbluebutton.SystemConfiguration
|
||||
import org.bigbluebutton.common2.msgs.MuteUserCmdMsg
|
||||
import org.bigbluebutton.core.apps.PermisssionCheck
|
||||
import org.bigbluebutton.core.models.VoiceUsers
|
||||
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
||||
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
|
||||
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
||||
|
||||
trait MuteUserCmdMsgHdlr {
|
||||
this: MeetingActor =>
|
||||
trait MuteUserCmdMsgHdlrDefault {
|
||||
def handleMuteUserCmdMsg(msg: MuteUserCmdMsg): Unit = {
|
||||
println("**************** MuteUserCmdMsgHdlrDefault ")
|
||||
}
|
||||
}
|
||||
|
||||
trait MuteUserCmdMsgHdlrPermCheck extends MuteUserCmdMsgHdlrDefault with SystemConfiguration {
|
||||
this: UsersApp =>
|
||||
|
||||
val liveMeeting: LiveMeeting
|
||||
val outGW: OutMsgRouter
|
||||
|
||||
def handleMuteUserCmdMsg(msg: MuteUserCmdMsg) {
|
||||
log.info("Received mute user request. meetingId=" + props.meetingProp.intId + " userId="
|
||||
override def handleMuteUserCmdMsg(msg: MuteUserCmdMsg): Unit = {
|
||||
println("**************** MuteUserCmdMsgHdlrPermCheck ")
|
||||
|
||||
val isAllowed = PermisssionCheck.isAllowed(
|
||||
PermisssionCheck.MOD_LEVEL,
|
||||
PermisssionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.body.mutedBy
|
||||
)
|
||||
|
||||
if (applyPermissionCheck && !isAllowed) {
|
||||
val meetingId = liveMeeting.props.meetingProp.intId
|
||||
val reason = "No permission to mute user in meeting."
|
||||
PermisssionCheck.ejectUserForFailedPermission(meetingId, msg.body.mutedBy, reason, outGW)
|
||||
} else {
|
||||
super.handleMuteUserCmdMsg(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait MuteUserCmdMsgHdlr extends MuteUserCmdMsgHdlrDefault {
|
||||
this: UsersApp =>
|
||||
|
||||
val liveMeeting: LiveMeeting
|
||||
val outGW: OutMsgRouter
|
||||
|
||||
override def handleMuteUserCmdMsg(msg: MuteUserCmdMsg) {
|
||||
println("**************** MuteUserCmdMsgHdlr ")
|
||||
|
||||
val meetingId = liveMeeting.props.meetingProp.intId
|
||||
val voiceConf = liveMeeting.props.voiceProp.voiceConf
|
||||
|
||||
log.info("Received mute user request. meetingId=" + meetingId + " userId="
|
||||
+ msg.body.userId)
|
||||
for {
|
||||
u <- VoiceUsers.findWithIntId(liveMeeting.voiceUsers, msg.body.userId)
|
||||
} yield {
|
||||
log.info("Send mute user request. meetingId=" + props.meetingProp.intId + " userId=" + u.intId + " user=" + u)
|
||||
val event = MsgBuilder.buildMuteUserInVoiceConfSysMsg(props.meetingProp.intId, props.voiceProp.voiceConf,
|
||||
log.info("Send mute user request. meetingId=" + meetingId + " userId=" + u.intId + " user=" + u)
|
||||
val event = MsgBuilder.buildMuteUserInVoiceConfSysMsg(meetingId, voiceConf,
|
||||
u.voiceUserId, !u.muted)
|
||||
outGW.send(event)
|
||||
}
|
||||
|
@ -21,7 +21,9 @@ class UsersApp(
|
||||
with SetRecordingStatusCmdMsgHdlr
|
||||
with GetRecordingStatusReqMsgHdlr
|
||||
with AssignPresenterReqMsgHdlr
|
||||
with EjectUserFromMeetingCmdMsgHdlr {
|
||||
with EjectUserFromMeetingCmdMsgHdlr
|
||||
with MuteUserCmdMsgHdlr
|
||||
with MuteUserCmdMsgHdlrPermCheck {
|
||||
|
||||
val log = Logging(context.system, getClass)
|
||||
}
|
||||
|
@ -13,8 +13,10 @@ object PresentationPodFactory {
|
||||
|
||||
case class PresentationPod(id: String, ownerId: String, currentPresenter: String, authorizedPresenters: Vector[String],
|
||||
presentations: collection.immutable.Map[String, Presentation]) {
|
||||
def addPresentation(presentation: Presentation): PresentationPod = copy(presentations =
|
||||
presentations + (presentation.id -> presentation))
|
||||
def addPresentation(presentation: Presentation): PresentationPod = {
|
||||
copy(presentations = presentations + (presentation.id -> presentation))
|
||||
}
|
||||
|
||||
def removePresentation(id: String): PresentationPod = copy(presentations = presentations - id)
|
||||
|
||||
def addAuthorizedPresenter(userId: String): PresentationPod = copy(authorizedPresenters = authorizedPresenters :+ userId)
|
||||
@ -42,14 +44,39 @@ case class PresentationPod(id: String, ownerId: String, currentPresenter: String
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def getPresentationsSize(): Int = {
|
||||
presentations.values.size
|
||||
}
|
||||
}
|
||||
|
||||
case class PresentationPodManager(presentationPods: collection.immutable.Map[String, PresentationPod]) {
|
||||
|
||||
def addPod(presPod: PresentationPod): PresentationPodManager = copy(presentationPods + (presPod.id -> presPod))
|
||||
def removePod(podId: String): PresentationPodManager = copy(presentationPods = presentationPods - podId)
|
||||
def addPod(presPod: PresentationPod): PresentationPodManager = {
|
||||
copy(presentationPods = presentationPods + (presPod.id -> presPod))
|
||||
}
|
||||
|
||||
def removePod(podId: String): PresentationPodManager = {
|
||||
copy(presentationPods = presentationPods - podId)
|
||||
}
|
||||
|
||||
def getNumberOfPods(): Int = presentationPods.size
|
||||
def getPod(podId: String): Option[PresentationPod] = presentationPods.get(podId)
|
||||
def getAllPresentationPodsInMeeting(): Vector[PresentationPod] = presentationPods.values.toVector
|
||||
def updatePresentationPod(presPod: PresentationPod): PresentationPodManager = addPod(presPod)
|
||||
|
||||
def addPresentationToPod(podId: String, pres: Presentation): PresentationPodManager = {
|
||||
val updatedManager = for {
|
||||
pod <- getPod(podId)
|
||||
} yield {
|
||||
val updatedPod = pod.addPresentation(pres)
|
||||
updatePresentationPod(updatedPod)
|
||||
}
|
||||
|
||||
updatedManager match {
|
||||
case Some(ns) => ns
|
||||
case None => this
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -167,4 +167,5 @@ object Roles {
|
||||
val PRESENTER_ROLE = "PRESENTER"
|
||||
val VIEWER_ROLE = "VIEWER"
|
||||
val GUEST_ROLE = "GUEST"
|
||||
val AUTHENTICATED_ROLE = "AUTHENTICATED"
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ class MeetingActor(
|
||||
with BreakoutApp2x
|
||||
with UsersApp2x
|
||||
|
||||
with PermisssionCheck
|
||||
with UserBroadcastCamStartMsgHdlr
|
||||
with UserJoinMeetingReqMsgHdlr
|
||||
with UserJoinMeetingAfterReconnectReqMsgHdlr
|
||||
@ -71,8 +70,9 @@ class MeetingActor(
|
||||
with UserDisconnectedFromGlobalAudioMsgHdlr
|
||||
with MuteAllExceptPresentersCmdMsgHdlr
|
||||
with MuteMeetingCmdMsgHdlr
|
||||
with MuteMeetingCmdMsgHdlrCheckPerm
|
||||
with IsMeetingMutedReqMsgHdlr
|
||||
with MuteUserCmdMsgHdlr
|
||||
|
||||
with EjectUserFromVoiceCmdMsgHdlr
|
||||
with EndMeetingSysCmdMsgHdlr
|
||||
with DestroyMeetingSysCmdMsgHdlr
|
||||
@ -265,7 +265,7 @@ class MeetingActor(
|
||||
case m: UserMutedInVoiceConfEvtMsg => handleUserMutedInVoiceConfEvtMsg(m)
|
||||
case m: UserTalkingInVoiceConfEvtMsg => handleUserTalkingInVoiceConfEvtMsg(m)
|
||||
case m: RecordingStartedVoiceConfEvtMsg => handleRecordingStartedVoiceConfEvtMsg(m)
|
||||
case m: MuteUserCmdMsg => handleMuteUserCmdMsg(m)
|
||||
case m: MuteUserCmdMsg => usersApp.handleMuteUserCmdMsg(m)
|
||||
case m: MuteAllExceptPresentersCmdMsg => handleMuteAllExceptPresentersCmdMsg(m)
|
||||
case m: EjectUserFromVoiceCmdMsg => handleEjectUserFromVoiceCmdMsg(m)
|
||||
case m: IsMeetingMutedReqMsg => handleIsMeetingMutedReqMsg(m)
|
||||
@ -295,7 +295,6 @@ class MeetingActor(
|
||||
case m: PresentationConversionUpdateSysPubMsg => presentationApp2x.handle(m, liveMeeting, msgBus)
|
||||
case m: PresentationPageCountErrorSysPubMsg => presentationApp2x.handle(m, liveMeeting, msgBus)
|
||||
case m: PresentationPageGeneratedSysPubMsg => presentationApp2x.handle(m, liveMeeting, msgBus)
|
||||
case m: PresentationConversionCompletedSysPubMsg => presentationApp2x.handle(m, liveMeeting, msgBus)
|
||||
case m: AssignPresenterReqMsg => handlePresenterChange(m)
|
||||
|
||||
// Presentation Pods
|
||||
@ -304,6 +303,7 @@ class MeetingActor(
|
||||
case m: GetPresentationInfoReqMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
|
||||
case m: GetAllPresentationPodsReqMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
|
||||
case m: SetCurrentPresentationPubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
|
||||
case m: PresentationConversionCompletedSysPubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
|
||||
|
||||
// Caption
|
||||
case m: EditCaptionHistoryPubMsg => captionApp2x.handle(m, liveMeeting, msgBus)
|
||||
|
@ -1,17 +1,43 @@
|
||||
package org.bigbluebutton.core2.message.handlers
|
||||
|
||||
import org.bigbluebutton.SystemConfiguration
|
||||
import org.bigbluebutton.common2.msgs._
|
||||
import org.bigbluebutton.core.OutMessageGateway
|
||||
import org.bigbluebutton.core.apps.PermisssionCheck
|
||||
import org.bigbluebutton.core.models.{ VoiceUserState, VoiceUsers }
|
||||
import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
|
||||
import org.bigbluebutton.core2.MeetingStatus2x
|
||||
|
||||
trait MuteMeetingCmdMsgHdlr {
|
||||
trait MuteMeetingCmdMsgHdlrDefault {
|
||||
def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg): Unit = {}
|
||||
}
|
||||
|
||||
trait MuteMeetingCmdMsgHdlrCheckPerm extends MuteMeetingCmdMsgHdlrDefault with SystemConfiguration {
|
||||
this: MeetingActor =>
|
||||
|
||||
val outGW: OutMsgRouter
|
||||
|
||||
def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg) {
|
||||
override def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg): Unit = {
|
||||
val isAllowed = PermisssionCheck.isAllowed(
|
||||
PermisssionCheck.MOD_LEVEL,
|
||||
PermisssionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.body.mutedBy
|
||||
)
|
||||
|
||||
if (applyPermissionCheck && !isAllowed) {
|
||||
val meetingId = liveMeeting.props.meetingProp.intId
|
||||
val reason = "No permission to mute meeting."
|
||||
PermisssionCheck.ejectUserForFailedPermission(meetingId, msg.body.mutedBy, reason, outGW)
|
||||
} else {
|
||||
super.handleMuteMeetingCmdMsg(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait MuteMeetingCmdMsgHdlr extends MuteMeetingCmdMsgHdlrDefault {
|
||||
this: MeetingActor =>
|
||||
|
||||
val outGW: OutMsgRouter
|
||||
|
||||
override def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg): Unit = {
|
||||
|
||||
def build(meetingId: String, userId: String, muted: Boolean, mutedBy: String): BbbCommonEnvCoreMsg = {
|
||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
||||
|
@ -166,11 +166,12 @@ object MsgBuilder {
|
||||
BbbCommonEnvCoreMsg(envelope, event)
|
||||
}
|
||||
|
||||
def buildUserEjectedFromMeetingEvtMsg(meetingId: String, userId: String, ejectedBy: String): BbbCommonEnvCoreMsg = {
|
||||
def buildUserEjectedFromMeetingEvtMsg(meetingId: String, userId: String,
|
||||
ejectedBy: String, reason: String): BbbCommonEnvCoreMsg = {
|
||||
val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, userId)
|
||||
val envelope = BbbCoreEnvelope(UserEjectedFromMeetingEvtMsg.NAME, routing)
|
||||
val header = BbbClientMsgHeader(UserEjectedFromMeetingEvtMsg.NAME, meetingId, userId)
|
||||
val body = UserEjectedFromMeetingEvtMsgBody(userId, ejectedBy)
|
||||
val body = UserEjectedFromMeetingEvtMsgBody(userId, ejectedBy, reason)
|
||||
val event = UserEjectedFromMeetingEvtMsg(header, body)
|
||||
|
||||
BbbCommonEnvCoreMsg(envelope, event)
|
||||
|
@ -1,8 +1,22 @@
|
||||
package org.bigbluebutton.core2.message.senders
|
||||
|
||||
import org.bigbluebutton.common2.msgs.BbbCommonEnvCoreMsg
|
||||
import org.bigbluebutton.core.OutMessageGateway
|
||||
import org.bigbluebutton.core.running.OutMsgRouter
|
||||
|
||||
trait Sender {
|
||||
object Sender {
|
||||
|
||||
def sendUserEjectedFromMeetingClientEvtMsg(meetingId: String, userId: String,
|
||||
ejectedBy: String, reason: String, outGW: OutMsgRouter): Unit = {
|
||||
val ejectFromMeetingClientEvent = MsgBuilder.buildUserEjectedFromMeetingEvtMsg(
|
||||
meetingId, userId, ejectedBy, reason
|
||||
)
|
||||
outGW.send(ejectFromMeetingClientEvent)
|
||||
}
|
||||
|
||||
def sendUserEjectedFromMeetingSystemMsg(meetingId: String, userId: String,
|
||||
ejectedBy: String, outGW: OutMsgRouter): Unit = {
|
||||
val ejectFromMeetingSystemEvent = MsgBuilder.buildDisconnectClientSysMsg(
|
||||
meetingId, userId, ejectedBy
|
||||
)
|
||||
outGW.send(ejectFromMeetingSystemEvent)
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ case class UserEmojiChangedEvtMsgBody(userId: String, emoji: String)
|
||||
*/
|
||||
object UserEjectedFromMeetingEvtMsg { val NAME = "UserEjectedFromMeetingEvtMsg" }
|
||||
case class UserEjectedFromMeetingEvtMsg(header: BbbClientMsgHeader, body: UserEjectedFromMeetingEvtMsgBody) extends StandardMsg
|
||||
case class UserEjectedFromMeetingEvtMsgBody(userId: String, ejectedBy: String)
|
||||
case class UserEjectedFromMeetingEvtMsgBody(userId: String, ejectedBy: String, reason: String)
|
||||
|
||||
object AssignPresenterReqMsg { val NAME = "AssignPresenterReqMsg"}
|
||||
case class AssignPresenterReqMsg(header: BbbClientMsgHeader, body: AssignPresenterReqMsgBody) extends StandardMsg
|
||||
|
Loading…
Reference in New Issue
Block a user