Skip to content

Commit

Permalink
Refactor handlers, role validation
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpetri1 committed Apr 30, 2022
1 parent 7851d54 commit 19bbb41
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 173 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class PresentationPodHdlrs(implicit val context: ActorContext)
with PresentationPageCountErrorPubMsgHdlr
with PresentationUploadedFileTooLargeErrorPubMsgHdlr
with PresentationUploadTokenReqMsgHdlr
with PresentationWithAnnotationsMsgHdlr
with ResizeAndMovePagePubMsgHdlr
with SyncGetPresentationPodsMsgHdlr
with RemovePresentationPodPubMsgHdlr
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package org.bigbluebutton.core.apps.presentationpod

import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.util.RandomStringGenerator
import org.bigbluebutton.core.models.{ PresentationPod, PresentationPage, PresentationInPod }

trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
this: PresentationPodHdlrs =>

def buildStoreAnnotationsInRedisSysMsg(annotations: StoredAnnotations, liveMeeting: LiveMeeting): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(StoreAnnotationsInRedisSysMsg.NAME, routing)
val body = StoreAnnotationsInRedisSysMsgBody(annotations)
val header = BbbCoreHeaderWithMeetingId(StoreAnnotationsInRedisSysMsg.NAME, liveMeeting.props.meetingProp.intId)
val event = StoreAnnotationsInRedisSysMsg(header, body)

BbbCommonEnvCoreMsg(envelope, event)
}

def buildStoreExportJobInRedisSysMsg(exportJob: ExportJob, liveMeeting: LiveMeeting): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(StoreExportJobInRedisSysMsg.NAME, routing)
val body = StoreExportJobInRedisSysMsgBody(exportJob)
val header = BbbCoreHeaderWithMeetingId(StoreExportJobInRedisSysMsg.NAME, liveMeeting.props.meetingProp.intId)
val event = StoreExportJobInRedisSysMsg(header, body)

BbbCommonEnvCoreMsg(envelope, event)
}

def buildPresentationUploadTokenSysPubMsg(parentId: String, userId: String, presentationUploadToken: String, filename: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(PresentationUploadTokenSysPubMsg.NAME, routing)
val header = BbbClientMsgHeader(PresentationUploadTokenSysPubMsg.NAME, parentId, userId)
val body = PresentationUploadTokenSysPubMsgBody("DEFAULT_PRESENTATION_POD", presentationUploadToken, filename, parentId)
val event = PresentationUploadTokenSysPubMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}

def handleMakePresentationWithAnnotationDownloadReqMsg(m: MakePresentationWithAnnotationDownloadReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {

val meetingId = liveMeeting.props.meetingProp.intId

// Whiteboard ID
val presId: String = m.body.presId match {
case "" => PresentationPodsApp.getAllPresentationPodsInMeeting(state).flatMap(_.getCurrentPresentation.map(_.id)).mkString
case _ => m.body.presId
}

val allPages: Boolean = m.body.allPages // Whether or not all pages of the presentation should be exported
val pages: List[Int] = m.body.pages // Desired presentation pages for export

// Determine page amount
val presentationPods: Vector[PresentationPod] = state.presentationPodManager.getAllPresentationPodsInMeeting()

val currentPres = presentationPods.flatMap(_.getCurrentPresentation()).headOption

currentPres match {
case None =>
log.error(s"No presentation set in meeting ${meetingId}")
return
case _ => ()
}

val pageCount = currentPres.get.pages.size
val pagesRange: List[Int] = if (allPages) (1 to pageCount).toList else pages

var storeAnnotationPages = new Array[PresentationPageForExport](pagesRange.size)
var resultingPage = 0

for (pageNumber <- pagesRange) {
if (pageNumber < 1 || pageNumber > pageCount) {
println(pagesRange.length)
log.error(s"Page ${pageNumber} requested for export out of range, aborting")
return
}

var whiteboardId = s"${presId}/${pageNumber.toString}"
val presentationPage: PresentationPage = currentPres.get.pages(whiteboardId)
val xOffset: Double = presentationPage.xOffset
val yOffset: Double = presentationPage.yOffset
val widthRatio: Double = presentationPage.widthRatio
val heightRatio: Double = presentationPage.heightRatio
val whiteboardHistory: Array[AnnotationVO] = liveMeeting.wbModel.getHistory(whiteboardId)

storeAnnotationPages(resultingPage) = new PresentationPageForExport(pageNumber, xOffset, yOffset, widthRatio, heightRatio, whiteboardHistory)
resultingPage += 1
}

val jobId = RandomStringGenerator.randomAlphanumericString(16)

// 1) Send Annotations to Redis
var annotations = new StoredAnnotations(jobId, presId, storeAnnotationPages)
bus.outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations, liveMeeting))

// 2) Insert Export Job in Redis
val jobType = "PresentationWithAnnotationDownloadJob"
val presLocation = s"/var/bigbluebutton/${meetingId}/${meetingId}/${presId}"
val exportJob = new ExportJob(jobId, jobType, "annotated_slides", presId, presLocation, allPages, pagesRange, meetingId, "")
var job = buildStoreExportJobInRedisSysMsg(exportJob, liveMeeting)
bus.outGW.send(job)
}

def handleExportPresentationWithAnnotationReqMsg(m: ExportPresentationWithAnnotationReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {

val meetingId = liveMeeting.props.meetingProp.intId
val userId = m.header.userId

if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, userId)) {
val reason = "No permission to export presentation."
PermissionCheck.ejectUserForFailedPermission(meetingId, userId, reason, bus.outGW, liveMeeting)
return
}

val parentMeetingId: String = m.body.parentMeetingId

val presId: String = PresentationPodsApp.getAllPresentationPodsInMeeting(state).flatMap(_.getCurrentPresentation.map(_.id)).mkString
val allPages: Boolean = m.body.allPages

val presentationPods: Vector[PresentationPod] = state.presentationPodManager.getAllPresentationPodsInMeeting()
val currentPres = presentationPods.flatMap(_.getCurrentPresentation()).headOption

currentPres match {
case None =>
log.error(s"No presentation set in meeting ${meetingId}")
return
case _ => ()
}

val currentPage: PresentationPage = PresentationInPod.getCurrentPage(currentPres.get).get

val pageCount = currentPres.get.pages.size
val pagesRange: List[Int] = if (allPages) (1 to pageCount).toList else List(currentPage.num)

var storeAnnotationPages = new Array[PresentationPageForExport](pagesRange.size)
var resultingPage = 0

for (pageNumber <- pagesRange) {
var whiteboardId = s"${presId}/${pageNumber.toString}"
val presentationPage: PresentationPage = currentPres.get.pages(whiteboardId)
val xOffset: Double = presentationPage.xOffset
val yOffset: Double = presentationPage.yOffset
val widthRatio: Double = presentationPage.widthRatio
val heightRatio: Double = presentationPage.heightRatio
val whiteboardHistory: Array[AnnotationVO] = liveMeeting.wbModel.getHistory(whiteboardId)

storeAnnotationPages(resultingPage) = new PresentationPageForExport(pageNumber, xOffset, yOffset, widthRatio, heightRatio, whiteboardHistory)
resultingPage += 1
}

val presentationUploadToken: String = PresentationPodsApp.generateToken("DEFAULT_PRESENTATION_POD", userId)
val jobId = RandomStringGenerator.randomAlphanumericString(16)
val filename: String = s"${liveMeeting.props.meetingProp.name}-annotated"

// Informs bbb-web about the token so that when we use it to upload the presentation, it is able to look it up in the list of tokens
bus.outGW.send(buildPresentationUploadTokenSysPubMsg(parentMeetingId, userId, presentationUploadToken, filename))

// 1) Send Annotations to Redis
var annotations = new StoredAnnotations(jobId, presId, storeAnnotationPages)
bus.outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations, liveMeeting))

// 2) Insert Export Job in Redis
val jobType: String = "PresentationWithAnnotationExportJob"
val presLocation = s"/var/bigbluebutton/${meetingId}/${meetingId}/${presId}"
val exportJob = new ExportJob(jobId, jobType, filename, presId, presLocation, allPages, pagesRange, parentMeetingId, presentationUploadToken)
var job = buildStoreExportJobInRedisSysMsg(exportJob, liveMeeting)
bus.outGW.send(job)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,8 @@ class StoreExportJobInRedisPresAnnEvent extends AbstractPresentationWithAnnotati
eventMap.put(JOB_TYPE, jobType)
}

def setMeetingName(meetingName: String) {
eventMap.put(MEETING_NAME, meetingName)
}

def setPresName(presName: String) {
eventMap.put(PRES_NAME, presName)
def setFilename(filename: String) {
eventMap.put(FILENAME, filename)
}

def setPresId(presId: String) {
Expand Down Expand Up @@ -71,8 +67,7 @@ class StoreExportJobInRedisPresAnnEvent extends AbstractPresentationWithAnnotati
object StoreExportJobInRedisPresAnnEvent {
protected final val JOB_ID = "jobId"
protected final val JOB_TYPE = "jobType"
protected final val MEETING_NAME = "meetingName"
protected final val PRES_NAME = "presName"
protected final val FILENAME = "filename"
protected final val PRES_ID = "presId"
protected final val PRES_LOCATION = "presLocation"
protected final val ALL_PAGES = "allPages"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import org.bigbluebutton.core.apps.webcam.WebcamApp2x
import org.bigbluebutton.core.apps.whiteboard.WhiteboardApp2x
import org.bigbluebutton.core.bus._
import org.bigbluebutton.core.models.{ Users2x, VoiceUsers, _ }
import org.bigbluebutton.core.util.RandomStringGenerator
import org.bigbluebutton.core2.{ MeetingStatus2x, Permissions }
import org.bigbluebutton.core2.message.handlers._
import org.bigbluebutton.core2.message.handlers.meeting._
Expand Down Expand Up @@ -496,8 +495,8 @@ class MeetingActor(
// Presentation
case m: PreuploadedPresentationsSysPubMsg => presentationApp2x.handle(m, liveMeeting, msgBus)
case m: AssignPresenterReqMsg => state = handlePresenterChange(m, state)
case m: MakePresentationWithAnnotationDownloadReqMsg => handleMakePresentationWithAnnotationDownloadReqMsg(m, state, liveMeeting)
case m: ExportPresentationWithAnnotationReqMsg => handleExportPresentationWithAnnotationReqMsg(m, state, liveMeeting)
case m: MakePresentationWithAnnotationDownloadReqMsg => presentationPodsApp.handleMakePresentationWithAnnotationDownloadReqMsg(m, state, liveMeeting, msgBus)
case m: ExportPresentationWithAnnotationReqMsg => presentationPodsApp.handleExportPresentationWithAnnotationReqMsg(m, state, liveMeeting, msgBus)
case m: NewPresAnnFileAvailableMsg => log.info("***** New PDF with annotations available.")

// Presentation Pods
Expand Down Expand Up @@ -721,158 +720,6 @@ class MeetingActor(

}

def buildStoreAnnotationsInRedisSysMsg(annotations: StoredAnnotations): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(StoreAnnotationsInRedisSysMsg.NAME, routing)
val body = StoreAnnotationsInRedisSysMsgBody(annotations)
val header = BbbCoreHeaderWithMeetingId(StoreAnnotationsInRedisSysMsg.NAME, liveMeeting.props.meetingProp.intId)
val event = StoreAnnotationsInRedisSysMsg(header, body)

BbbCommonEnvCoreMsg(envelope, event)
}

def buildStoreExportJobInRedisSysMsg(exportJob: ExportJob): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(StoreExportJobInRedisSysMsg.NAME, routing)
val body = StoreExportJobInRedisSysMsgBody(exportJob)
val header = BbbCoreHeaderWithMeetingId(StoreExportJobInRedisSysMsg.NAME, liveMeeting.props.meetingProp.intId)
val event = StoreExportJobInRedisSysMsg(header, body)

BbbCommonEnvCoreMsg(envelope, event)
}

def buildPresentationUploadTokenSysPubMsg(parentId: String, userId: String, presentationUploadToken: String, filename: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(PresentationUploadTokenSysPubMsg.NAME, routing)
val header = BbbClientMsgHeader(PresentationUploadTokenSysPubMsg.NAME, parentId, userId)
val body = PresentationUploadTokenSysPubMsgBody("DEFAULT_PRESENTATION_POD", presentationUploadToken, filename, parentId)
val event = PresentationUploadTokenSysPubMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}

def handleMakePresentationWithAnnotationDownloadReqMsg(m: MakePresentationWithAnnotationDownloadReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting): Unit = {

val meetingId = liveMeeting.props.meetingProp.intId
val meetingName: String = liveMeeting.props.meetingProp.name

// Whiteboard ID
val presId: String = m.body.presId match {
case "" => getMeetingInfoPresentationDetails().id
case _ => m.body.presId
}

val allPages: Boolean = m.body.allPages // Whether or not all pages of the presentation should be exported
val pages: List[Int] = m.body.pages // Desired presentation pages for export

// Determine page amount
val presentationPods: Vector[PresentationPod] = state.presentationPodManager.getAllPresentationPodsInMeeting()

val currentPres = presentationPods.flatMap(_.getCurrentPresentation()).headOption

currentPres match {
case None =>
log.error(s"No presentation set in meeting ${meetingId}")
return
case _ => ()
}

val pageCount = currentPres.get.pages.size
val pagesRange: List[Int] = if (allPages) (1 to pageCount).toList else pages

var storeAnnotationPages = new Array[PresentationPageForExport](pagesRange.size)
var resultingPage = 0

for (pageNumber <- pagesRange) {
if (pageNumber < 1 || pageNumber > pageCount) {
println(pagesRange.length)
log.error(s"Page ${pageNumber} requested for export out of range, aborting")
return
}

var whiteboardId = s"${presId}/${pageNumber.toString}"
val presentationPage: PresentationPage = currentPres.get.pages(whiteboardId)
val xOffset: Double = presentationPage.xOffset
val yOffset: Double = presentationPage.yOffset
val widthRatio: Double = presentationPage.widthRatio
val heightRatio: Double = presentationPage.heightRatio
val whiteboardHistory: Array[AnnotationVO] = liveMeeting.wbModel.getHistory(whiteboardId)

storeAnnotationPages(resultingPage) = new PresentationPageForExport(pageNumber, xOffset, yOffset, widthRatio, heightRatio, whiteboardHistory)
resultingPage += 1
}

val jobId = RandomStringGenerator.randomAlphanumericString(16)

// 1) Send Annotations to Redis
var annotations = new StoredAnnotations(jobId, presId, storeAnnotationPages)
outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations))

// 2) Insert Export Job in Redis
val jobType = "PresentationWithAnnotationDownloadJob"
val presLocation = s"/var/bigbluebutton/${meetingId}/${meetingId}/${presId}"
val exportJob = new ExportJob(jobId, jobType, meetingName, currentPres.get.name, presId, presLocation, allPages, pagesRange, meetingId, "")
var job = buildStoreExportJobInRedisSysMsg(exportJob)
outGW.send(job)
}

def handleExportPresentationWithAnnotationReqMsg(m: ExportPresentationWithAnnotationReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting): Unit = {

val meetingId = liveMeeting.props.meetingProp.intId
val meetingName: String = liveMeeting.props.meetingProp.name
val userId = m.header.userId
val presId: String = getMeetingInfoPresentationDetails.id
val parentMeetingId: String = m.body.parentMeetingId
val allPages: Boolean = m.body.allPages

val presentationPods: Vector[PresentationPod] = state.presentationPodManager.getAllPresentationPodsInMeeting()
val currentPres = presentationPods.flatMap(_.getCurrentPresentation()).headOption

currentPres match {
case None =>
log.error(s"No presentation set in meeting ${meetingId}")
return
case _ => ()
}

val currentPage: PresentationPage = PresentationInPod.getCurrentPage(currentPres.get).get

val pageCount = currentPres.get.pages.size
val pagesRange: List[Int] = if (allPages) (1 to pageCount).toList else List(currentPage.num)

var storeAnnotationPages = new Array[PresentationPageForExport](pagesRange.size)
var resultingPage = 0

for (pageNumber <- pagesRange) {
var whiteboardId = s"${presId}/${pageNumber.toString}"
val presentationPage: PresentationPage = currentPres.get.pages(whiteboardId)
val xOffset: Double = presentationPage.xOffset
val yOffset: Double = presentationPage.yOffset
val widthRatio: Double = presentationPage.widthRatio
val heightRatio: Double = presentationPage.heightRatio
val whiteboardHistory: Array[AnnotationVO] = liveMeeting.wbModel.getHistory(whiteboardId)

storeAnnotationPages(resultingPage) = new PresentationPageForExport(pageNumber, xOffset, yOffset, widthRatio, heightRatio, whiteboardHistory)
resultingPage += 1
}

val presentationUploadToken: String = PresentationPodsApp.generateToken("DEFAULT_PRESENTATION_POD", userId)
val jobId = RandomStringGenerator.randomAlphanumericString(16)

// Informs bbb-web about the token so that when we use it to upload the presentation, it is able to look it up in the list of tokens
outGW.send(buildPresentationUploadTokenSysPubMsg(parentMeetingId, userId, presentationUploadToken, currentPres.get.name))

// 1) Send Annotations to Redis
var annotations = new StoredAnnotations(jobId, presId, storeAnnotationPages)
outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations))

// 2) Insert Export Job in Redis
val jobType: String = "PresentationWithAnnotationExportJob"
val presLocation = s"/var/bigbluebutton/${meetingId}/${meetingId}/${presId}"
val exportJob = new ExportJob(jobId, jobType, meetingName, currentPres.get.name, presId, presLocation, allPages, pagesRange, parentMeetingId, presentationUploadToken)
var job = buildStoreExportJobInRedisSysMsg(exportJob)
outGW.send(job)
}

def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsersInternalMsg) {
state = removeUsersWithExpiredUserLeftFlag(liveMeeting, state)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ class ExportAnnotationsActor(

ev.setJobId(msg.body.exportJob.jobId)
ev.setJobType(msg.body.exportJob.jobType)
ev.setMeetingName(msg.body.exportJob.meetingName)
ev.setPresName(msg.body.exportJob.presName)
ev.setFilename(msg.body.exportJob.filename)
ev.setPresId(msg.body.exportJob.presId)
ev.setPresLocation(msg.body.exportJob.presLocation)
ev.setAllPages(msg.body.exportJob.allPages.toString)
Expand Down
Loading

0 comments on commit 19bbb41

Please sign in to comment.