diff --git a/.github/workflows/automated-tests.yml b/.github/workflows/automated-tests.yml index eb8d3fe00f..3cacf5a908 100644 --- a/.github/workflows/automated-tests.yml +++ b/.github/workflows/automated-tests.yml @@ -13,7 +13,7 @@ jobs: build-install-and-test: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: ./build/get_external_dependencies.sh - run: ./build/setup.sh bbb-apps-akka - run: ./build/setup.sh bbb-config diff --git a/.github/workflows/check-merge-conflict.yml b/.github/workflows/check-merge-conflict.yml index 5e62e8886d..f4b27d2af6 100644 --- a/.github/workflows/check-merge-conflict.yml +++ b/.github/workflows/check-merge-conflict.yml @@ -6,8 +6,13 @@ on: - opened - synchronize +permissions: + contents: read + jobs: main: + permissions: + pull-requests: write # for eps1lon/actions-label-merge-conflict to label PRs runs-on: ubuntu-latest steps: - name: Check for dirty pull requests diff --git a/akka-bbb-apps/build.sbt b/akka-bbb-apps/build.sbt index e79e761ab9..a22969a951 100755 --- a/akka-bbb-apps/build.sbt +++ b/akka-bbb-apps/build.sbt @@ -18,7 +18,7 @@ val compileSettings = Seq( "-Xlint", "-Ywarn-dead-code", "-language:_", - "-target:jvm-1.11", + "-target:11", "-encoding", "UTF-8" ), javacOptions ++= List( @@ -48,7 +48,7 @@ lazy val bbbAppsAkka = (project in file(".")).settings(name := "bbb-apps-akka", // Config file is in ./.scalariform.conf scalariformAutoformat := true -scalaVersion := "2.13.4" +scalaVersion := "2.13.9" //----------- // Packaging // diff --git a/akka-bbb-apps/project/Dependencies.scala b/akka-bbb-apps/project/Dependencies.scala index 92efe20fb9..7e404ff5fe 100755 --- a/akka-bbb-apps/project/Dependencies.scala +++ b/akka-bbb-apps/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { object Versions { // Scala - val scala = "2.13.4" + val scala = "2.13.9" val junit = "4.12" val junitInterface = "0.11" val scalactic = "3.0.8" @@ -26,7 +26,7 @@ object Dependencies { val codec = "1.15" // BigBlueButton - val bbbCommons = "0.0.21-SNAPSHOT" + val bbbCommons = "0.0.22-SNAPSHOT" // Test val scalaTest = "3.2.11" diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/presentationpod/PresentationWithAnnotationsMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/presentationpod/PresentationWithAnnotationsMsgHdlr.scala index 288fe2968f..a3b1ac5e1d 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/presentationpod/PresentationWithAnnotationsMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/presentationpod/PresentationWithAnnotationsMsgHdlr.scala @@ -13,6 +13,12 @@ import java.io.File trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait { this: PresentationPodHdlrs => + object JobTypes { + val DOWNLOAD = "PresentationWithAnnotationDownloadJob" + val CAPTURE_PRESENTATION = "PresentationWithAnnotationExportJob" + val CAPTURE_NOTES = "PadCaptureJob" + } + def buildStoreAnnotationsInRedisSysMsg(annotations: StoredAnnotations, liveMeeting: LiveMeeting): BbbCommonEnvCoreMsg = { val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka") val envelope = BbbCoreEnvelope(StoreAnnotationsInRedisSysMsg.NAME, routing) @@ -111,7 +117,6 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait { log.error(s"Presentation ${presId} not found in meeting ${meetingId}") } else { - val jobType: String = "PresentationWithAnnotationDownloadJob" val jobId: String = RandomStringGenerator.randomAlphanumericString(16); val allPages: Boolean = m.body.allPages val pageCount = currentPres.get.pages.size @@ -120,7 +125,7 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait { val pages: List[Int] = m.body.pages // Desired presentation pages for export val pagesRange: List[Int] = if (allPages) (1 to pageCount).toList else pages - val exportJob: ExportJob = new ExportJob(jobId, jobType, "annotated_slides", presId, presLocation, allPages, pagesRange, meetingId, ""); + val exportJob: ExportJob = new ExportJob(jobId, JobTypes.DOWNLOAD, "annotated_slides", presId, presLocation, allPages, pagesRange, meetingId, ""); val storeAnnotationPages: List[PresentationPageForExport] = getPresentationPagesForExport(pagesRange, pageCount, presId, currentPres, liveMeeting); // Send Export Job to Redis @@ -147,7 +152,6 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait { } else { val jobId: String = RandomStringGenerator.randomAlphanumericString(16); - val jobType = "PresentationWithAnnotationExportJob" val allPages: Boolean = m.allPages val pageCount = currentPres.get.pages.size @@ -172,7 +176,7 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait { // 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)) - val exportJob: ExportJob = new ExportJob(jobId, jobType, filename, presId, presLocation, allPages, pagesRange, parentMeetingId, presentationUploadToken) + val exportJob: ExportJob = new ExportJob(jobId, JobTypes.CAPTURE_PRESENTATION, filename, presId, presLocation, allPages, pagesRange, parentMeetingId, presentationUploadToken) val storeAnnotationPages: List[PresentationPageForExport] = getPresentationPagesForExport(pagesRange, pageCount, presId, currentPres, liveMeeting); // Send Export Job to Redis @@ -210,13 +214,12 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait { val userId: String = "system" val jobId: String = s"${m.body.breakoutId}-notes" // Used as the temporaryPresentationId upon upload - val jobType = "PadCaptureJob" val filename = m.body.filename val presentationUploadToken: String = PresentationPodsApp.generateToken("DEFAULT_PRESENTATION_POD", userId) bus.outGW.send(buildPresentationUploadTokenSysPubMsg(m.body.parentMeetingId, userId, presentationUploadToken, filename)) - val exportJob = new ExportJob(jobId, jobType, filename, m.body.padId, "", true, List(), m.body.parentMeetingId, presentationUploadToken) + val exportJob = new ExportJob(jobId, JobTypes.CAPTURE_NOTES, filename, m.body.padId, "", true, List(), m.body.parentMeetingId, presentationUploadToken) val job = buildStoreExportJobInRedisSysMsg(exportJob, liveMeeting) bus.outGW.send(job) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/ChangeLockSettingsInMeetingCmdMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/ChangeLockSettingsInMeetingCmdMsgHdlr.scala index a7e738bfed..9fd98bdfaa 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/ChangeLockSettingsInMeetingCmdMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/ChangeLockSettingsInMeetingCmdMsgHdlr.scala @@ -42,6 +42,17 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait { MeetingStatus2x.setPermissions(liveMeeting.status, settings) + // Dial-in + def buildLockMessage(meetingId: String, userId: String, lockedBy: String, locked: Boolean): BbbCommonEnvCoreMsg = { + val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId) + val envelope = BbbCoreEnvelope(UserLockedInMeetingEvtMsg.NAME, routing) + val body = UserLockedInMeetingEvtMsgBody(userId, locked, lockedBy) + val header = BbbClientMsgHeader(UserLockedInMeetingEvtMsg.NAME, meetingId, userId) + val event = UserLockedInMeetingEvtMsg(header, body) + + BbbCommonEnvCoreMsg(envelope, event) + } + if (oldPermissions.disableCam != settings.disableCam) { if (settings.disableCam) { val notifyEvent = MsgBuilder.buildNotifyAllInMeetingEvtMsg( @@ -55,24 +66,6 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait { outGW.send(notifyEvent) LockSettingsUtil.enforceCamLockSettingsForAllUsers(liveMeeting, outGW) - - // Dial-in - def buildLockMessage(meetingId: String, userId: String, lockedBy: String, locked: Boolean): BbbCommonEnvCoreMsg = { - val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId) - val envelope = BbbCoreEnvelope(UserLockedInMeetingEvtMsg.NAME, routing) - val body = UserLockedInMeetingEvtMsgBody(userId, locked, lockedBy) - val header = BbbClientMsgHeader(UserLockedInMeetingEvtMsg.NAME, meetingId, userId) - val event = UserLockedInMeetingEvtMsg(header, body) - - BbbCommonEnvCoreMsg(envelope, event) - } - - VoiceUsers.findAll(liveMeeting.voiceUsers) foreach { vu => - if (vu.intId.startsWith(IntIdPrefixType.DIAL_IN)) { // only Dial-in users need this - val eventExplicitLock = buildLockMessage(liveMeeting.props.meetingProp.intId, vu.intId, msg.body.setBy, settings.disableMic) - outGW.send(eventExplicitLock) - } - } } else { val notifyEvent = MsgBuilder.buildNotifyAllInMeetingEvtMsg( liveMeeting.props.meetingProp.intId, @@ -97,8 +90,12 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait { Vector() ) outGW.send(notifyEvent) - - // Apply lock settings when disableMic from false to true. + VoiceUsers.findAll(liveMeeting.voiceUsers) foreach { vu => + if (vu.intId.startsWith(IntIdPrefixType.DIAL_IN)) { // only Dial-in users need this + val eventExplicitLock = buildLockMessage(liveMeeting.props.meetingProp.intId, vu.intId, msg.body.setBy, settings.disableMic) + outGW.send(eventExplicitLock) + } + } LockSettingsUtil.enforceLockSettingsForAllVoiceUsers(liveMeeting, outGW) } else { val notifyEvent = MsgBuilder.buildNotifyAllInMeetingEvtMsg( diff --git a/akka-bbb-fsesl/build.sbt b/akka-bbb-fsesl/build.sbt index 5171f7ebef..88ee24c714 100755 --- a/akka-bbb-fsesl/build.sbt +++ b/akka-bbb-fsesl/build.sbt @@ -18,7 +18,7 @@ val compileSettings = Seq( "-Xlint", "-Ywarn-dead-code", "-language:_", - "-target:jvm-1.11", + "-target:11", "-encoding", "UTF-8" ), javacOptions ++= List( @@ -27,7 +27,7 @@ val compileSettings = Seq( ) ) -scalaVersion := "2.13.4" +scalaVersion := "2.13.9" resolvers += Resolver.sonatypeRepo("releases") diff --git a/akka-bbb-fsesl/project/Dependencies.scala b/akka-bbb-fsesl/project/Dependencies.scala index b540b352fa..81540e1705 100755 --- a/akka-bbb-fsesl/project/Dependencies.scala +++ b/akka-bbb-fsesl/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { object Versions { // Scala - val scala = "2.13.4" + val scala = "2.13.9" val junitInterface = "0.11" val scalactic = "3.0.8" @@ -21,8 +21,8 @@ object Dependencies { val codec = "1.15" // BigBlueButton - val bbbCommons = "0.0.21-SNAPSHOT" - val bbbFsesl = "0.0.8-SNAPSHOT" + val bbbCommons = "0.0.22-SNAPSHOT" + val bbbFsesl = "0.0.9-SNAPSHOT" // Test val scalaTest = "3.2.11" diff --git a/bbb-common-message/build.sbt b/bbb-common-message/build.sbt index 77c39f36f7..d99c62fb88 100755 --- a/bbb-common-message/build.sbt +++ b/bbb-common-message/build.sbt @@ -1,7 +1,7 @@ import org.bigbluebutton.build._ -version := "0.0.21-SNAPSHOT" +version := "0.0.22-SNAPSHOT" val compileSettings = Seq( organization := "org.bigbluebutton", @@ -12,7 +12,7 @@ val compileSettings = Seq( "-Xlint", "-Ywarn-dead-code", "-language:_", - "-target:jvm-1.11", + "-target:11", "-encoding", "UTF-8" ), javacOptions ++= List( @@ -55,7 +55,7 @@ scalariformAutoformat := true // Do not append Scala versions to the generated artifacts //crossPaths := false -scalaVersion := "2.13.4" +scalaVersion := "2.13.9" // This forbids including Scala related libraries into the dependency //autoScalaLibrary := false diff --git a/bbb-common-message/project/Dependencies.scala b/bbb-common-message/project/Dependencies.scala index 10e865a85c..c2d169de06 100644 --- a/bbb-common-message/project/Dependencies.scala +++ b/bbb-common-message/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { object Versions { // Scala - val scala = "2.13.4" + val scala = "2.13.9" val junit = "4.12" val junitInterface = "0.11" val scalactic = "3.0.8" diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala index b80d64488d..db7458fa15 100755 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala @@ -9,16 +9,16 @@ case class DurationProps(duration: Int, createdTime: Long, createdDate: String, endWhenNoModerator: Boolean, endWhenNoModeratorDelayInMinutes: Int) case class MeetingProp( - name: String, - extId: String, - intId: String, - meetingCameraCap: Int, - maxPinnedCameras: Int, - isBreakout: Boolean, - disabledFeatures: Vector[String], - notifyRecordingIsOn: Boolean, - uploadExternalDescription: String, - uploadExternalUrl: String, + name: String, + extId: String, + intId: String, + meetingCameraCap: Int, + maxPinnedCameras: Int, + isBreakout: Boolean, + disabledFeatures: Vector[String], + notifyRecordingIsOn: Boolean, + presentationUploadExternalDescription: String, + presentationUploadExternalUrl: String, ) case class BreakoutProps( diff --git a/bbb-common-web/build.sbt b/bbb-common-web/build.sbt index 5e55ff5410..9d44d00e47 100755 --- a/bbb-common-web/build.sbt +++ b/bbb-common-web/build.sbt @@ -11,7 +11,7 @@ val compileSettings = Seq( "-Xlint", "-Ywarn-dead-code", "-language:_", - "-target:jvm-1.11", + "-target:11", "-encoding", "UTF-8" ), javacOptions ++= List( @@ -40,7 +40,7 @@ lazy val commonWeb = (project in file(".")).settings(name := "bbb-common-web", l // Config file is in ./.scalariform.conf scalariformAutoformat := true -scalaVersion := "2.13.4" +scalaVersion := "2.13.9" //----------- // Packaging // diff --git a/bbb-common-web/project/Dependencies.scala b/bbb-common-web/project/Dependencies.scala index 891ce546e0..d6247adca0 100644 --- a/bbb-common-web/project/Dependencies.scala +++ b/bbb-common-web/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { object Versions { // Scala - val scala = "2.13.4" + val scala = "2.13.9" val junit = "4.12" val junitInterface = "0.11" val scalactic = "3.0.8" @@ -34,7 +34,7 @@ object Dependencies { val text = "1.10.0" // BigBlueButton - val bbbCommons = "0.0.21-SNAPSHOT" + val bbbCommons = "0.0.22-SNAPSHOT" // Test val scalaTest = "3.2.11" diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java index 365f9f514d..05b61bcb1f 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java @@ -73,8 +73,8 @@ public class ApiParams { public static final String DISABLED_FEATURES = "disabledFeatures"; public static final String NOTIFY_RECORDING_IS_ON = "notifyRecordingIsOn"; - public static final String UPLOAD_EXTERNAL_DESCRIPTION = "uploadExternalDescription"; - public static final String UPLOAD_EXTERNAL_URL = "uploadExternalUrl"; + public static final String PRESENTATION_UPLOAD_EXTERNAL_DESCRIPTION = "presentationUploadExternalDescription"; + public static final String PRESENTATION_UPLOAD_EXTERNAL_URL = "presentationUploadExternalUrl"; public static final String BREAKOUT_ROOMS_CAPTURE_SLIDES = "breakoutRoomsCaptureSlides"; public static final String BREAKOUT_ROOMS_CAPTURE_NOTES = "breakoutRoomsCaptureNotes"; diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java index 36b9a1d37a..096e155328 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java @@ -419,7 +419,7 @@ public class MeetingService implements MessageListener { m.getMuteOnStart(), m.getAllowModsToUnmuteUsers(), m.getAllowModsToEjectCameras(), m.getMeetingKeepEvents(), m.breakoutRoomsParams, m.lockSettingsParams, m.getHtml5InstanceId(), m.getGroups(), m.getDisabledFeatures(), m.getNotifyRecordingIsOn(), - m.getUploadExternalDescription(), m.getUploadExternalUrl()); + m.getPresentationUploadExternalDescription(), m.getPresentationUploadExternalUrl()); } private String formatPrettyDate(Long timestamp) { diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java index ed95087a9c..3dc73110f9 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java @@ -81,6 +81,7 @@ public class ParamsProcessorUtil { private String defaultHTML5ClientUrl; private String defaultGuestWaitURL; private Boolean allowRequestsWithoutSession = false; + private Integer defaultHttpSessionTimeout = 14400; private Boolean useDefaultAvatar = false; private String defaultAvatarURL; private String defaultGuestPolicy; @@ -104,8 +105,8 @@ public class ParamsProcessorUtil { private boolean defaultKeepEvents = false; private Boolean useDefaultLogo; private String defaultLogoURL; - private String defaultUploadExternalDescription = ""; - private String defaultUploadExternalUrl = ""; + private String defaultPresentationUploadExternalDescription = ""; + private String defaultPresentationUploadExternalUrl = ""; private boolean defaultBreakoutRoomsEnabled = true; private boolean defaultBreakoutRoomsRecord; @@ -639,14 +640,14 @@ public class ParamsProcessorUtil { guestPolicy = params.get(ApiParams.GUEST_POLICY); } - String uploadExternalDescription = defaultUploadExternalDescription; - if (!StringUtils.isEmpty(params.get(ApiParams.UPLOAD_EXTERNAL_DESCRIPTION))) { - uploadExternalDescription = params.get(ApiParams.UPLOAD_EXTERNAL_DESCRIPTION); + String presentationUploadExternalDescription = defaultPresentationUploadExternalDescription; + if (!StringUtils.isEmpty(params.get(ApiParams.PRESENTATION_UPLOAD_EXTERNAL_DESCRIPTION))) { + presentationUploadExternalDescription = params.get(ApiParams.PRESENTATION_UPLOAD_EXTERNAL_DESCRIPTION); } - String uploadExternalUrl = defaultUploadExternalUrl; - if (!StringUtils.isEmpty(params.get(ApiParams.UPLOAD_EXTERNAL_URL))) { - uploadExternalUrl = params.get(ApiParams.UPLOAD_EXTERNAL_URL); + String presentationUploadExternalUrl = defaultPresentationUploadExternalUrl; + if (!StringUtils.isEmpty(params.get(ApiParams.PRESENTATION_UPLOAD_EXTERNAL_URL))) { + presentationUploadExternalUrl = params.get(ApiParams.PRESENTATION_UPLOAD_EXTERNAL_URL); } String meetingLayout = defaultMeetingLayout; @@ -737,8 +738,8 @@ public class ParamsProcessorUtil { .withGroups(groups) .withDisabledFeatures(listOfDisabledFeatures) .withNotifyRecordingIsOn(notifyRecordingIsOn) - .withUploadExternalDescription(uploadExternalDescription) - .withUploadExternalUrl(uploadExternalUrl) + .withPresentationUploadExternalDescription(presentationUploadExternalDescription) + .withPresentationUploadExternalUrl(presentationUploadExternalUrl) .build(); if (!StringUtils.isEmpty(params.get(ApiParams.MODERATOR_ONLY_MESSAGE))) { @@ -846,6 +847,14 @@ public class ParamsProcessorUtil { return allowRequestsWithoutSession; } + public Integer getDefaultHttpSessionTimeout() { + return defaultHttpSessionTimeout; + } + + public void setDefaultHttpSessionTimeout(Integer value) { + this.defaultHttpSessionTimeout = value; + } + public String getDefaultLogoutUrl() { if ((StringUtils.isEmpty(defaultLogoutUrl)) || "default".equalsIgnoreCase(defaultLogoutUrl)) { return defaultServerUrl; @@ -1445,12 +1454,12 @@ public class ParamsProcessorUtil { this.defaultNotifyRecordingIsOn = notifyRecordingIsOn; } - public void setUploadExternalDescription(String uploadExternalDescription) { - this.defaultUploadExternalDescription = uploadExternalDescription; + public void setPresentationUploadExternalDescription(String presentationUploadExternalDescription) { + this.defaultPresentationUploadExternalDescription = presentationUploadExternalDescription; } - public void setUploadExternalUrl(String uploadExternalUrl) { - this.defaultUploadExternalUrl = uploadExternalUrl; + public void setPresentationUploadExternalUrl(String presentationUploadExternalUrl) { + this.defaultPresentationUploadExternalUrl = presentationUploadExternalUrl; } public void setBbbVersion(String version) { diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java index aa9c4c38eb..b3daf17117 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/domain/Meeting.java @@ -97,8 +97,8 @@ public class Meeting { private Boolean allowRequestsWithoutSession = false; private Boolean allowModsToEjectCameras = false; private Boolean meetingKeepEvents; - private String uploadExternalDescription; - private String uploadExternalUrl; + private String presentationUploadExternalDescription; + private String presentationUploadExternalUrl; private Integer meetingExpireIfNoUserJoinedInMinutes = 5; private Integer meetingExpireWhenLastUserLeftInMinutes = 1; @@ -123,8 +123,8 @@ public class Meeting { intMeetingId = builder.internalId; disabledFeatures = builder.disabledFeatures; notifyRecordingIsOn = builder.notifyRecordingIsOn; - uploadExternalDescription = builder.uploadExternalDescription; - uploadExternalUrl = builder.uploadExternalUrl; + presentationUploadExternalDescription = builder.presentationUploadExternalDescription; + presentationUploadExternalUrl = builder.presentationUploadExternalUrl; if (builder.viewerPass == null){ viewerPass = ""; } else { @@ -424,11 +424,11 @@ public class Meeting { return notifyRecordingIsOn; } - public String getUploadExternalDescription() { - return uploadExternalDescription; + public String getPresentationUploadExternalDescription() { + return presentationUploadExternalDescription; } - public String getUploadExternalUrl() { - return uploadExternalUrl; + public String getPresentationUploadExternalUrl() { + return presentationUploadExternalUrl; } public String getWelcomeMessageTemplate() { @@ -863,8 +863,8 @@ public class Meeting { private String learningDashboardAccessToken; private ArrayList disabledFeatures; private Boolean notifyRecordingIsOn; - private String uploadExternalDescription; - private String uploadExternalUrl; + private String presentationUploadExternalDescription; + private String presentationUploadExternalUrl; private int duration; private String webVoice; private String telVoice; @@ -993,13 +993,13 @@ public class Meeting { return this; } - public Builder withUploadExternalDescription(String d) { - this.uploadExternalDescription = d; + public Builder withPresentationUploadExternalDescription(String d) { + this.presentationUploadExternalDescription = d; return this; } - public Builder withUploadExternalUrl(String u) { - this.uploadExternalUrl = u; + public Builder withPresentationUploadExternalUrl(String u) { + this.presentationUploadExternalUrl = u; return this; } diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/converters/messages/CreateMeetingMessage.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/converters/messages/CreateMeetingMessage.java index 893f87e375..6a21fcf8f9 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/converters/messages/CreateMeetingMessage.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/converters/messages/CreateMeetingMessage.java @@ -25,8 +25,8 @@ public class CreateMeetingMessage { public final String learningDashboardAccessToken; public final ArrayList disabledFeatures; public final Boolean notifyRecordingIsOn; - public final String uploadExternalDescription; - public final String uploadExternalUrl; + public final String presentationUploadExternalDescription; + public final String presentationUploadExternalUrl; public final Long createTime; public final String createDate; public final Map metadata; @@ -38,8 +38,8 @@ public class CreateMeetingMessage { String viewerPass, String learningDashboardAccessToken, ArrayList disabledFeatures, Boolean notifyRecordingIsOn, - String uploadExternalDescription, - String uploadExternalUrl, + String presentationUploadExternalDescription, + String presentationUploadExternalUrl, Long createTime, String createDate, Map metadata) { this.id = id; this.externalId = externalId; @@ -58,8 +58,8 @@ public class CreateMeetingMessage { this.learningDashboardAccessToken = learningDashboardAccessToken; this.disabledFeatures = disabledFeatures; this.notifyRecordingIsOn = notifyRecordingIsOn; - this.uploadExternalDescription = uploadExternalDescription; - this.uploadExternalUrl = uploadExternalUrl; + this.presentationUploadExternalDescription = presentationUploadExternalDescription; + this.presentationUploadExternalUrl = presentationUploadExternalUrl; this.createTime = createTime; this.createDate = createDate; this.metadata = metadata; diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ParamsUtil.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ParamsUtil.java index 75148e4bd2..6e6697ad23 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ParamsUtil.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ParamsUtil.java @@ -18,7 +18,7 @@ public class ParamsUtil { public static final String INVALID_CHARS = ","; public static String stripControlChars(String text) { - return text.replaceAll("\\p{Cc}", ""); + return text.replaceAll("\\p{Cc}", "").trim(); } public static String escapeHTMLTags(String value) { diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java b/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java index 85781752f0..d3bf85e813 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java @@ -43,8 +43,8 @@ public interface IBbbWebApiGWApp { ArrayList groups, ArrayList disabledFeatures, Boolean notifyRecordingIsOn, - String uploadExternalDescription, - String uploadExternalUrl); + String presentationUploadExternalDescription, + String presentationUploadExternalUrl); void registerUser(String meetingID, String internalUserId, String fullname, String role, String externUserID, String authToken, String avatarURL, diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala index 3fdd680262..04e6342972 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala @@ -150,8 +150,8 @@ class BbbWebApiGWApp( groups: java.util.ArrayList[Group], disabledFeatures: java.util.ArrayList[String], notifyRecordingIsOn: java.lang.Boolean, - uploadExternalDescription: String, - uploadExternalUrl: String): Unit = { + presentationUploadExternalDescription: String, + presentationUploadExternalUrl: String): Unit = { val disabledFeaturesAsVector: Vector[String] = disabledFeatures.asScala.toVector @@ -164,8 +164,8 @@ class BbbWebApiGWApp( isBreakout = isBreakout.booleanValue(), disabledFeaturesAsVector, notifyRecordingIsOn, - uploadExternalDescription, - uploadExternalUrl + presentationUploadExternalDescription, + presentationUploadExternalUrl ) val durationProps = DurationProps( diff --git a/bbb-export-annotations/.npmrc b/bbb-export-annotations/.npmrc new file mode 100644 index 0000000000..b6f27f1359 --- /dev/null +++ b/bbb-export-annotations/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/bbb-export-annotations/lib/utils/logger.js b/bbb-export-annotations/lib/utils/logger.js index 7e65980b01..f54f13cfc9 100644 --- a/bbb-export-annotations/lib/utils/logger.js +++ b/bbb-export-annotations/lib/utils/logger.js @@ -1,13 +1,13 @@ const config = require('../../config'); -const { level } = config.log; +const {level} = config.log; const trace = level.toLowerCase() === 'trace'; const debug = trace || level.toLowerCase() === 'debug'; const date = () => new Date().toISOString(); const parse = (messages) => { - return messages.map(message => { + return messages.map((message) => { if (typeof message === 'object') return JSON.stringify(message); return message; diff --git a/bbb-export-annotations/lib/utils/message-builder.js b/bbb-export-annotations/lib/utils/message-builder.js new file mode 100644 index 0000000000..db2740a74f --- /dev/null +++ b/bbb-export-annotations/lib/utils/message-builder.js @@ -0,0 +1,88 @@ +const config = require('../../config'); + +const EXPORT_STATUSES = Object.freeze({ + COLLECTING: 'COLLECTING', + PROCESSING: 'PROCESSING', +}); + +class PresAnnStatusMsg { + constructor(exportJob, status = EXPORT_STATUSES.COLLECTING) { + this.message = { + envelope: { + name: config.log.msgName, + routing: { + sender: exportJob.module, + }, + timestamp: (new Date()).getTime(), + }, + core: { + header: { + name: config.log.msgName, + meetingId: exportJob.parentMeetingId, + userId: '', + }, + body: { + presId: exportJob.presId, + pageNumber: 1, + totalPages: JSON.parse(exportJob.pages).length, + status, + error: false, + }, + }, + }; + } + + build = (pageNumber = 1) => { + this.message.core.body.pageNumber = pageNumber; + this.message.envelope.timestamp = (new Date()).getTime(); + const event = JSON.stringify(this.message); + this.message.core.body.error = false; + return event; + }; + + setError = (error = true) => { + this.message.core.body.error = error; + }; + + setStatus = (status) => { + this.message.core.body.status = status; + }; + + static get EXPORT_STATUSES() { + return EXPORT_STATUSES; + } +}; + +class NewPresAnnFileAvailableMsg { + constructor(exportJob, link) { + this.message = { + envelope: { + name: config.notifier.msgName, + routing: { + sender: exportJob.module, + }, + timestamp: (new Date()).getTime(), + }, + core: { + header: { + name: config.notifier.msgName, + meetingId: exportJob.parentMeetingId, + userId: '', + }, + body: { + fileURI: link, + presId: exportJob.presId, + }, + }, + }; + } + + build = () => { + return JSON.stringify(this.message); + }; +}; + +module.exports = { + PresAnnStatusMsg, + NewPresAnnFileAvailableMsg, +}; diff --git a/bbb-export-annotations/package-lock.json b/bbb-export-annotations/package-lock.json index 4f7a91ce6b..051241a26b 100644 --- a/bbb-export-annotations/package-lock.json +++ b/bbb-export-annotations/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "axios": "^0.26.0", "form-data": "^4.0.0", + "lodash": "^4.17.21", "perfect-freehand": "^1.0.16", "probe-image-size": "^7.2.3", "redis": "^4.0.3", @@ -19,6 +20,10 @@ "devDependencies": { "eslint": "^8.20.0", "eslint-config-google": "^0.14.0" + }, + "engines": { + "node": "^16.16.0", + "npm": "^8.5.0" } }, "node_modules/@eslint/eslintrc": { @@ -920,6 +925,11 @@ "node": ">= 0.8.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2044,6 +2054,11 @@ "type-check": "~0.4.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/bbb-export-annotations/package.json b/bbb-export-annotations/package.json index ef16a596ca..130f5aa8f8 100644 --- a/bbb-export-annotations/package.json +++ b/bbb-export-annotations/package.json @@ -19,5 +19,9 @@ "devDependencies": { "eslint": "^8.20.0", "eslint-config-google": "^0.14.0" + }, + "engines": { + "node": "^16.16.0", + "npm": "^8.5.0" } } diff --git a/bbb-export-annotations/workers/collector.js b/bbb-export-annotations/workers/collector.js index b3762d5146..25b21347ff 100644 --- a/bbb-export-annotations/workers/collector.js +++ b/bbb-export-annotations/workers/collector.js @@ -8,6 +8,7 @@ const redis = require('redis'); const sanitize = require('sanitize-filename'); const stream = require('stream'); const WorkerStarter = require('../lib/utils/worker-starter'); +const {PresAnnStatusMsg} = require('../lib/utils/message-builder'); const {workerData} = require('worker_threads'); const {promisify} = require('util'); @@ -55,29 +56,7 @@ async function collectAnnotationsFromRedis() { const pdfFile = `${presFile}.pdf`; // Message to display conversion progress toast - const statusUpdate = { - envelope: { - name: config.log.msgName, - routing: { - sender: exportJob.module, - }, - timestamp: (new Date()).getTime(), - }, - core: { - header: { - name: config.log.msgName, - meetingId: exportJob.parentMeetingId, - userId: '', - }, - body: { - presId: exportJob.presId, - pageNumber: 1, - totalPages: pages.length, - status: 'COLLECTING', - error: false, - }, - }, - }; + const statusUpdate = new PresAnnStatusMsg(exportJob); if (fs.existsSync(pdfFile)) { for (const p of pages) { @@ -103,35 +82,32 @@ async function collectAnnotationsFromRedis() { try { cp.spawnSync(config.shared.pdftocairo, extract_png_from_pdf, {shell: false}); } catch (error) { - const error_reason = `PDFtoCairo failed extracting slide ${pageNumber}`; - logger.error(`${error_reason} in job ${jobId}: ${error.message}`); - statusUpdate.core.body.status = error_reason; - statusUpdate.core.body.error = true; + logger.error(`PDFtoCairo failed extracting slide ${pageNumber} in job ${jobId}: ${error.message}`); + statusUpdate.setError(); } - statusUpdate.core.body.pageNumber = pageNumber; - statusUpdate.envelope.timestamp = (new Date()).getTime(); - await client.publish(config.redis.channels.publish, JSON.stringify(statusUpdate)); - statusUpdate.core.body.error = false; + await client.publish(config.redis.channels.publish, statusUpdate.build(pageNumber)); } - // If PNG file already available - } else if (fs.existsSync(`${presFile}.png`)) { - fs.copyFileSync(`${presFile}.png`, path.join(dropbox, 'slide1.png')); - await client.publish(config.redis.channels.publish, JSON.stringify(statusUpdate)); - // If JPEG file available - } else if (fs.existsSync(`${presFile}.jpeg`)) { - fs.copyFileSync(`${presFile}.jpeg`, path.join(dropbox, 'slide1.jpeg')); - await client.publish(config.redis.channels.publish, JSON.stringify(statusUpdate)); } else { - statusUpdate.core.body.error = true; - await client.publish(config.redis.channels.publish, JSON.stringify(statusUpdate)); - client.disconnect(); - return logger.error(`Presentation file missing for job ${exportJob.jobId}`); + if (fs.existsSync(`${presFile}.png`)) { + // PNG file available + fs.copyFileSync(`${presFile}.png`, path.join(dropbox, 'slide1.png')); + } else if (fs.existsSync(`${presFile}.jpeg`)) { + // JPEG file available + fs.copyFileSync(`${presFile}.jpeg`, path.join(dropbox, 'slide1.jpeg')); + await client.publish(config.redis.channels.publish, statusUpdate.build()); + } else { + await client.publish(config.redis.channels.publish, statusUpdate.build()); + client.disconnect(); + return logger.error(`No PDF, PNG or JPEG file available for job ${jobId}`); + } + + await client.publish(config.redis.channels.publish, statusUpdate.build()); } client.disconnect(); - const process = new WorkerStarter({jobId, statusUpdate}); + const process = new WorkerStarter({jobId}); process.process(); } diff --git a/bbb-export-annotations/workers/notifier.js b/bbb-export-annotations/workers/notifier.js index 94bbcda1ce..3371de9a06 100644 --- a/bbb-export-annotations/workers/notifier.js +++ b/bbb-export-annotations/workers/notifier.js @@ -5,6 +5,7 @@ const FormData = require('form-data'); const redis = require('redis'); const axios = require('axios').default; const path = require('path'); +const {NewPresAnnFileAvailableMsg} = require('../lib/utils/message-builder'); const {workerData} = require('worker_threads'); const [jobType, jobId, filename] = [workerData.jobType, workerData.jobId, workerData.filename]; @@ -31,30 +32,10 @@ async function notifyMeetingActor() { exportJob.parentMeetingId, exportJob.parentMeetingId, exportJob.presId, 'pdf', jobId, filename); - const notification = { - envelope: { - name: config.notifier.msgName, - routing: { - sender: exportJob.module, - }, - timestamp: (new Date()).getTime(), - }, - core: { - header: { - name: config.notifier.msgName, - meetingId: exportJob.parentMeetingId, - userId: '', - }, - body: { - fileURI: link, - presId: exportJob.presId, - }, - }, - }; + const notification = new NewPresAnnFileAvailableMsg(exportJob, link); logger.info(`Annotated PDF available at ${link}`); - await client.publish(config.redis.channels.publish, - JSON.stringify(notification)); + await client.publish(config.redis.channels.publish, notification.build()); client.disconnect(); } diff --git a/bbb-export-annotations/workers/process.js b/bbb-export-annotations/workers/process.js index 3798832c85..a61a6ba5e3 100644 --- a/bbb-export-annotations/workers/process.js +++ b/bbb-export-annotations/workers/process.js @@ -10,14 +10,16 @@ const sanitize = require('sanitize-filename'); const {getStrokePoints, getStrokeOutlinePoints} = require('perfect-freehand'); const probe = require('probe-image-size'); const redis = require('redis'); +const {PresAnnStatusMsg} = require('../lib/utils/message-builder'); -const [jobId, statusUpdate] = [workerData.jobId, workerData.statusUpdate]; - +const jobId = workerData.jobId; const logger = new Logger('presAnn Process Worker'); logger.info('Processing PDF for job ' + jobId); -statusUpdate.core.body.status = 'PROCESSING'; const dropbox = path.join(config.shared.presAnnDropboxDir, jobId); +const job = fs.readFileSync(path.join(dropbox, 'job')); +const exportJob = JSON.parse(job); +const statusUpdate = new PresAnnStatusMsg(exportJob, PresAnnStatusMsg.EXPORT_STATUSES.PROCESSING); // General utilities for rendering SVGs resembling Tldraw as much as possible function align_to_pango(alignment) { @@ -157,10 +159,8 @@ function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxW try { cp.spawnSync(config.shared.imagemagick, commands, {shell: false}); } catch (error) { - const error_reason = 'ImageMagick failed to render textbox'; - logger.error(`${error_reason} in job ${jobId}: ${error.message}`); - statusUpdate.core.body.status = error_reason; - statusUpdate.core.body.error = true; + logger.error(`ImageMagick failed to render textbox in job ${jobId}: ${error.message}`); + statusUpdate.setError(); } } @@ -596,7 +596,7 @@ function overlay_shape_label(svg, annotation) { const fontSize = text_size_to_px(annotation.style.size, annotation.style.scale); const textAlign = 'center'; const text = annotation.label; - const id = annotation.id; + const id = sanitize(annotation.id); const rotation = rad_to_degree(annotation.rotation); const [shape_width, shape_height] = annotation.size; @@ -641,7 +641,7 @@ function overlay_sticky(svg, annotation) { const textColor = '#0d0d0d'; // For sticky notes const text = annotation.text; - const id = annotation.id; + const id = sanitize(annotation.id); render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth); @@ -701,7 +701,7 @@ function overlay_text(svg, annotation) { const fontSize = text_size_to_px(annotation.style.size, annotation.style.scale); const textAlign = align_to_pango(annotation.style.textAlign); const text = annotation.text; - const id = annotation.id; + const id = sanitize(annotation.id); const rotation = rad_to_degree(annotation.rotation); const [textBox_x, textBox_y] = annotation.point; @@ -787,17 +787,13 @@ async function process_presentation_annotations() { client.on('error', (err) => logger.info('Redis Client Error', err)); - // 1. Get the job - const job = fs.readFileSync(path.join(dropbox, 'job')); - const exportJob = JSON.parse(job); - - // 2. Get the annotations + // Get the annotations const annotations = fs.readFileSync(path.join(dropbox, 'whiteboard')); const whiteboard = JSON.parse(annotations); const pages = JSON.parse(whiteboard.pages); const ghostScriptInput = []; - // 3. Convert annotations to SVG + // Convert annotations to SVG for (const currentSlide of pages) { const bgImagePath = path.join(dropbox, `slide${currentSlide.page}`); const svgBackgroundSlide = path.join(exportJob.presLocation, @@ -854,14 +850,7 @@ async function process_presentation_annotations() { } }); - // Dimensions converted to a pixel size which, - // when converted to points, will yield the desired - // dimension in pixels when read without conversion - - // e.g. say the background SVG dimensions are set to 1920x1080 pt - // Resize output to 2560x1440 px so that the SVG - // generates with the original size in pt. - + // Scale slide back to its original size const convertAnnotatedSlide = [ SVGfile, '--output-width', to_px(slideWidth), @@ -873,15 +862,11 @@ async function process_presentation_annotations() { cp.spawnSync(config.shared.cairosvg, convertAnnotatedSlide, {shell: false}); } catch (error) { logger.error(`Processing slide ${currentSlide.page} failed for job ${jobId}: ${error.message}`); - statusUpdate.core.body.error = true; + statusUpdate.setError(); } - statusUpdate.core.body.pageNumber = currentSlide.page; - statusUpdate.envelope.timestamp = (new Date()).getTime(); - - await client.publish(config.redis.channels.publish, JSON.stringify(statusUpdate)); + await client.publish(config.redis.channels.publish, statusUpdate.build(currentSlide.page)); ghostScriptInput.push(PDFfile); - statusUpdate.core.body.error = false; } // Create PDF output directory if it doesn't exist @@ -903,11 +888,7 @@ async function process_presentation_annotations() { try { cp.spawnSync(config.shared.ghostscript, mergePDFs, {shell: false}); } catch (error) { - const error_reason = 'GhostScript failed to merge PDFs'; - logger.error(`${error_reason} in job ${jobId}: ${error.message}`); - statusUpdate.core.body.status = error_reason; - statusUpdate.core.body.error = true; - await client.publish(config.redis.channels.publish, JSON.stringify(statusUpdate)); + return logger.error(`GhostScript failed to merge PDFs in job ${jobId}: ${error.message}`); } // Launch Notifier Worker depending on job type diff --git a/bbb-fsesl-client/build.sbt b/bbb-fsesl-client/build.sbt index c4f09d66c3..a45d6b1f72 100755 --- a/bbb-fsesl-client/build.sbt +++ b/bbb-fsesl-client/build.sbt @@ -2,7 +2,7 @@ import org.bigbluebutton.build._ description := "BigBlueButton custom FS-ESL client built on top of FS-ESL Java library." -version := "0.0.8-SNAPSHOT" +version := "0.0.9-SNAPSHOT" val compileSettings = Seq( organization := "org.bigbluebutton", @@ -13,7 +13,7 @@ val compileSettings = Seq( "-Xlint", "-Ywarn-dead-code", "-language:_", - "-target:jvm-1.11", + "-target:11", "-encoding", "UTF-8" ), javacOptions ++= List( @@ -52,7 +52,7 @@ crossPaths := false // This forbids including Scala related libraries into the dependency autoScalaLibrary := false -scalaVersion := "2.13.4" +scalaVersion := "2.13.9" publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath + "/.m2/repository"))) diff --git a/bbb-fsesl-client/project/Dependencies.scala b/bbb-fsesl-client/project/Dependencies.scala index 966a9eaacb..552b4e1a60 100644 --- a/bbb-fsesl-client/project/Dependencies.scala +++ b/bbb-fsesl-client/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { object Versions { // Scala - val scala = "2.13.4" + val scala = "2.13.9" // Libraries val netty = "3.2.10.Final" diff --git a/bigbluebutton-config/bigbluebutton-release b/bigbluebutton-config/bigbluebutton-release index 45d7bbb69a..51d2070582 100644 --- a/bigbluebutton-config/bigbluebutton-release +++ b/bigbluebutton-config/bigbluebutton-release @@ -1 +1 @@ -BIGBLUEBUTTON_RELEASE=2.6.0-beta.3 +BIGBLUEBUTTON_RELEASE=2.6.0-beta.4 diff --git a/bigbluebutton-config/bin/apply-lib.sh b/bigbluebutton-config/bin/apply-lib.sh index 270178b6b1..1a84436973 100644 --- a/bigbluebutton-config/bin/apply-lib.sh +++ b/bigbluebutton-config/bin/apply-lib.sh @@ -109,6 +109,15 @@ enableUFWRules() { ufw allow OpenSSH ufw allow "Nginx Full" ufw allow 16384:32768/udp + + # Check if coturn is running on this server and, if so, open firewall port + if systemctl status coturn > /dev/null; then + echo " - Local turnserver detected -- opening port 3478" + ufw allow 3478 + # echo " - Forcing FireFox to use turn server" + # yq w -i $HTML5_CONFIG public.kurento.forceRelayOnFirefox true + fi + ufw --force enable } diff --git a/bigbluebutton-config/bin/bbb-conf b/bigbluebutton-config/bin/bbb-conf index 4d753225ce..2f705d08b5 100755 --- a/bigbluebutton-config/bin/bbb-conf +++ b/bigbluebutton-config/bin/bbb-conf @@ -1686,8 +1686,7 @@ if [ -n "$HOST" ]; then echo "Restarting BigBlueButton $BIGBLUEBUTTON_RELEASE ..." - stop_bigbluebutton - start_bigbluebutton + systemctl restart bigbluebutton.target exit 0 fi @@ -1699,8 +1698,7 @@ if [ $RESTART ]; then echo "Restarting BigBlueButton $BIGBLUEBUTTON_RELEASE ..." - stop_bigbluebutton - start_bigbluebutton + systemctl restart bigbluebutton.target check_state fi diff --git a/bigbluebutton-html5/client/main.html b/bigbluebutton-html5/client/main.html index 5c9ad032fd..2f8b2de10d 100755 --- a/bigbluebutton-html5/client/main.html +++ b/bigbluebutton-html5/client/main.html @@ -127,7 +127,9 @@ with BigBlueButton; if not, see .
-
+
+
+