Skip to content

Commit

Permalink
Merge remote-tracking branch 'bbb/v3.0.x-release' into oct-25
Browse files Browse the repository at this point in the history
  • Loading branch information
antobinary committed Oct 25, 2024
2 parents 882d851 + 757b6eb commit cac5d72
Show file tree
Hide file tree
Showing 262 changed files with 7,667 additions and 4,462 deletions.
79 changes: 64 additions & 15 deletions .github/workflows/automated-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,24 +257,73 @@ jobs:
apt --purge -y remove apache2-bin
'
- name: Install BBB
uses: nick-fields/retry@v3
env:
NODE_EXTRA_CA_CERTS: /usr/local/share/ca-certificates/bbb-dev/bbb-dev-ca.crt
ACTIONS_RUNNER_DEBUG: true
with:
timeout_minutes: 25
max_attempts: 2
retry_on: any
command: |
sudo -i <<EOF
set -e
cd /root/ && wget -nv https://raw.githubusercontent.com/bigbluebutton/bbb-install/v3.0.x-release--no-mongo/bbb-install.sh -O bbb-install.sh
cat bbb-install.sh | sed "s|> /etc/apt/sources.list.d/bigbluebutton.list||g" | bash -s -- -v jammy-30-dev -s bbb-ci.test -j -d /certs/
bbb-conf --salt bbbci
sed -i "s/\"minify\": true,/\"minify\": false,/" /usr/share/etherpad-lite/settings.json
sudo yq e -i '.log_level = "TRACE"' /usr/share/bbb-graphql-middleware/config.yml
bbb-conf --restart
EOF
run: |
sudo -i <<'EOF'
set -e
cd /root/
wget -nv https://raw.githubusercontent.com/bigbluebutton/bbb-install/v3.0.x-release--no-mongo/bbb-install.sh -O bbb-install.sh
sed -i "s|> /etc/apt/sources.list.d/bigbluebutton.list||g" bbb-install.sh
chmod +x bbb-install.sh
COMMAND="./bbb-install.sh -v jammy-30-dev -s bbb-ci.test -j -d /certs/"
TIMEOUT=1500 # 25 minutes
MAX_RETRIES=3
RETRY_INTERVAL=60
RETRY_COUNT=0
SUCCESS=0
while [[ $RETRY_COUNT -lt $MAX_RETRIES ]]; do
echo "Attempt $((RETRY_COUNT + 1)) of $MAX_RETRIES to install BBB..."
# Run the command with timeout and handle its exit code
# Capture both stdout and stderr
COMMAND_EXIT_CODE=0
timeout $TIMEOUT $COMMAND || COMMAND_EXIT_CODE=$?
if [[ $COMMAND_EXIT_CODE -eq 0 ]]; then
SUCCESS=1
break
elif [[ $COMMAND_EXIT_CODE -eq 124 ]]; then
echo "Installation timed out after ${TIMEOUT} seconds. Retrying..."
else
echo "Installation failed with exit code $COMMAND_EXIT_CODE"
echo "Retrying installation within $RETRY_INTERVAL seconds..."
sleep $RETRY_INTERVAL
fi
echo "Stop any ongoing processes related to apt-get or dpkg that might be stuck"
# Use -q to suppress "no process found" messages
killall -q apt-get || true
killall -q dpkg || true
echo "Remove the lock files that may have been left behind"
# Group lock file removal for better readability
rm -f /var/lib/dpkg/lock-frontend
rm -f /var/lib/dpkg/lock
rm -f /var/cache/apt/archives/lock
echo "Reconfigure the package manager"
dpkg --configure -a
echo "Clean up any partially installed packages"
apt-get clean
apt-get autoremove
RETRY_COUNT=$((RETRY_COUNT + 1))
done
if [[ $SUCCESS -eq 0 ]]; then
echo "All attempts to install BBB failed."
exit 1
fi
bbb-conf --salt bbbci
sed -i "s/\"minify\": true,/\"minify\": false,/" /usr/share/etherpad-lite/settings.json
sudo yq e -i '.log_level = "TRACE"' /usr/share/bbb-graphql-middleware/config.yml
bbb-conf --restart
EOF
- name: List systemctl services
timeout-minutes: 1
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,23 @@ object BreakoutRoomsUtil extends SystemConfiguration {
checksum(apiCall.concat(baseString).concat(sharedSecret))
}

def joinParams(username: String, userId: String, isBreakout: Boolean, breakoutMeetingId: String,
password: String): (collection.immutable.Map[String, String], collection.immutable.Map[String, String]) = {
def joinParams(
username: String,
userId: String,
isBreakout: Boolean,
breakoutMeetingId: String,
avatarURL: String,
role: String,
password: String
): (collection.immutable.Map[String, String], collection.immutable.Map[String, String]) = {
val moderator = role == "MODERATOR"
val params = collection.immutable.HashMap(
"fullName" -> urlEncode(username),
"userID" -> urlEncode(userId),
"isBreakout" -> urlEncode(isBreakout.toString()),
"meetingID" -> urlEncode(breakoutMeetingId),
"avatarURL" -> urlEncode(avatarURL),
"userdata-bbb_parent_room_moderator" -> urlEncode(moderator.toString()),
"password" -> urlEncode(password),
"redirect" -> urlEncode("true")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,15 @@ object BreakoutHdlrHelpers extends SystemConfiguration {
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, userId)
apiCall = "join"
(redirectParams, redirectToHtml5Params) = BreakoutRoomsUtil.joinParams(user.name, userId + "-" + roomSequence, true,
externalMeetingId, liveMeeting.props.password.moderatorPass)
(redirectParams, redirectToHtml5Params) = BreakoutRoomsUtil.joinParams(
user.name,
userId + "-" + roomSequence,
true,
externalMeetingId,
user.avatar,
user.role,
liveMeeting.props.password.moderatorPass
)
// We generate a first url with redirect -> true
redirectBaseString = BreakoutRoomsUtil.createBaseString(redirectParams)
redirectJoinURL = BreakoutRoomsUtil.createJoinURL(bbbWebAPI, apiCall, redirectBaseString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
breakout.captureSlides,
breakout.captureNotesFilename,
breakout.captureSlidesFilename,
pluginProp = liveMeeting.props.pluginProp,
)

val event = buildCreateBreakoutRoomSysCmdMsg(liveMeeting.props.meetingProp.intId, roomDetail)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ trait DeleteGroupChatMessageReactionReqMsgHdlr extends HandlerHelpers {
val userIsAParticipant = groupChat.users.exists(u => u.id == user.intId)

if ((chatIsPrivate && userIsAParticipant) || !chatIsPrivate) {
val event = buildGroupChatMessageReactionDeletedEvtMsg(liveMeeting.props.meetingProp.intId, msg.header.userId, msg.body.chatId, gcMessage.id, msg.body.reactionEmoji)
val event = buildGroupChatMessageReactionDeletedEvtMsg(liveMeeting.props.meetingProp.intId, msg.header.userId, msg.body.chatId, gcMessage.id, msg.body.reactionEmoji, msg.body.reactionEmojiId)
bus.outGW.send(event)
ChatMessageReactionDAO.delete(liveMeeting.props.meetingProp.intId, gcMessage.id, msg.header.userId, msg.body.reactionEmoji)
ChatMessageReactionDAO.delete(liveMeeting.props.meetingProp.intId, gcMessage.id, msg.header.userId, msg.body.reactionEmoji, msg.body.reactionEmojiId)
} else {
val reason = "User isn't a participant of the chat"
PermissionCheck.ejectUserForFailedPermission(msg.header.meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ trait DeleteGroupChatMessageReqMsgHdlr extends HandlerHelpers {
chatLockedForUser = true
}

val userIsModerator = user.role != Roles.MODERATOR_ROLE
val userIsModerator = user.role == Roles.MODERATOR_ROLE

if (!userIsModerator && user.locked) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ trait EditGroupChatMessageReqMsgHdlr extends HandlerHelpers {
chatLockedForUser = true
}

val userIsModerator = user.role != Roles.MODERATOR_ROLE
val userIsModerator = user.role == Roles.MODERATOR_ROLE

if (!userIsModerator && user.locked) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
Expand All @@ -45,7 +45,7 @@ trait EditGroupChatMessageReqMsgHdlr extends HandlerHelpers {
}
}

if (!chatDisabled && editChatMessageDisabled && !(applyPermissionCheck && chatLocked) && !chatLockedForUser) {
if (!chatDisabled && !editChatMessageDisabled && !(applyPermissionCheck && chatLocked) && !chatLockedForUser) {
for {
gcMessage <- groupChat.msgs.find(gcm => gcm.id == msg.body.messageId)
} yield {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ trait SendGroupChatMessageReactionReqMsgHdlr extends HandlerHelpers {
chatLockedForUser = true
}

val userIsModerator = user.role != Roles.MODERATOR_ROLE
val userIsModerator = user.role == Roles.MODERATOR_ROLE

if (!userIsModerator && user.locked) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
Expand All @@ -52,9 +52,9 @@ trait SendGroupChatMessageReactionReqMsgHdlr extends HandlerHelpers {
val userIsAParticipant = groupChat.users.exists(u => u.id == user.intId)

if ((chatIsPrivate && userIsAParticipant) || !chatIsPrivate) {
val event = buildGroupChatMessageReactionSentEvtMsg(liveMeeting.props.meetingProp.intId, msg.header.userId, msg.body.chatId, gcMessage.id, msg.body.reactionEmoji)
val event = buildGroupChatMessageReactionSentEvtMsg(liveMeeting.props.meetingProp.intId, msg.header.userId, msg.body.chatId, gcMessage.id, msg.body.reactionEmoji, msg.body.reactionEmojiId)
bus.outGW.send(event)
ChatMessageReactionDAO.insert(liveMeeting.props.meetingProp.intId, gcMessage.id, msg.header.userId, msg.body.reactionEmoji)
ChatMessageReactionDAO.insert(liveMeeting.props.meetingProp.intId, gcMessage.id, msg.header.userId, msg.body.reactionEmoji, msg.body.reactionEmojiId)
} else {
val reason = "User isn't a participant of the chat"
PermissionCheck.ejectUserForFailedPermission(msg.header.meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,29 @@
package org.bigbluebutton.core.apps.plugin

import org.bigbluebutton.ClientSettings
import org.bigbluebutton.common2.msgs.PluginDataChannelDeleteEntryMsg
import org.bigbluebutton.core.apps.plugin.PluginHdlrHelpers.{ checkPermission, dataChannelCheckingLogic, defaultCreatorCheck }
import org.bigbluebutton.core.db.PluginDataChannelEntryDAO
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.{ Roles, Users2x }
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting }

trait PluginDataChannelDeleteEntryMsgHdlr extends HandlerHelpers {

def handle(msg: PluginDataChannelDeleteEntryMsg, state: MeetingState2x, liveMeeting: LiveMeeting): Unit = {
val pluginsDisabled: Boolean = liveMeeting.props.meetingProp.disabledFeatures.contains("plugins")
val meetingId = liveMeeting.props.meetingProp.intId

for {
_ <- if (!pluginsDisabled) Some(()) else None
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId)
} yield {
val pluginsConfig = ClientSettings.getPluginsFromConfig(ClientSettings.clientSettingsFromFile)

if (!pluginsConfig.contains(msg.body.pluginName)) {
println(s"Plugin '${msg.body.pluginName}' not found.")
} else if (!pluginsConfig(msg.body.pluginName).dataChannels.contains(msg.body.channelName)) {
println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.")
dataChannelCheckingLogic(liveMeeting, msg.header.userId, msg.body.pluginName, msg.body.channelName, (user, dc, meetingId) => {
val hasPermission = checkPermission(user, dc.replaceOrDeletePermission, defaultCreatorCheck(
meetingId, msg.body, msg.header.userId
))
if (!hasPermission.contains(true)) {
println(s"No permission to delete in plugin: '${msg.body.pluginName}', data channel: '${msg.body.channelName}'.")
} else {
val hasPermission = for {
replaceOrDeletePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).replaceOrDeletePermission
} yield {
replaceOrDeletePermission.toLowerCase match {
case "all" => true
case "moderator" => user.role == Roles.MODERATOR_ROLE
case "presenter" => user.presenter
case "creator" => {
val creatorUserId = PluginDataChannelEntryDAO.getEntryCreator(
meetingId,
msg.body.pluginName,
msg.body.channelName,
msg.body.subChannelName,
msg.body.entryId
)
creatorUserId == msg.header.userId
}
case _ => false
}
}

if (!hasPermission.contains(true)) {
println(s"No permission to delete in plugin: '${msg.body.pluginName}', data channel: '${msg.body.channelName}'.")
} else {
PluginDataChannelEntryDAO.delete(
meetingId,
msg.body.pluginName,
msg.body.channelName,
msg.body.subChannelName,
msg.body.entryId
)
}
PluginDataChannelEntryDAO.delete(
meetingId,
msg.body.pluginName,
msg.body.channelName,
msg.body.subChannelName,
msg.body.entryId
)
}
}
})
}
}
Original file line number Diff line number Diff line change
@@ -1,55 +1,30 @@
package org.bigbluebutton.core.apps.plugin

import org.bigbluebutton.common2.msgs.PluginDataChannelPushEntryMsg
import org.bigbluebutton.ClientSettings
import org.bigbluebutton.core.apps.plugin.PluginHdlrHelpers.{ checkPermission, dataChannelCheckingLogic, defaultCreatorCheck }
import org.bigbluebutton.core.db.PluginDataChannelEntryDAO
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.{ Roles, Users2x }
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting }

trait PluginDataChannelPushEntryMsgHdlr extends HandlerHelpers {

def handle(msg: PluginDataChannelPushEntryMsg, state: MeetingState2x, liveMeeting: LiveMeeting): Unit = {
val pluginsDisabled: Boolean = liveMeeting.props.meetingProp.disabledFeatures.contains("plugins")
val meetingId = liveMeeting.props.meetingProp.intId

for {
_ <- if (!pluginsDisabled) Some(()) else None
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId)
} yield {
val pluginsConfig = ClientSettings.getPluginsFromConfig(ClientSettings.clientSettingsFromFile)

if (!pluginsConfig.contains(msg.body.pluginName)) {
println(s"Plugin '${msg.body.pluginName}' not found.")
} else if (!pluginsConfig(msg.body.pluginName).dataChannels.contains(msg.body.channelName)) {
println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.")
dataChannelCheckingLogic(liveMeeting, msg.header.userId, msg.body.pluginName, msg.body.channelName, (user, dc, meetingId) => {
val hasPermission = checkPermission(user, dc.pushPermission)
if (!hasPermission.contains(true)) {
println(s"No permission to write in plugin: '${msg.body.pluginName}', data channel: '${msg.body.channelName}'.")
} else {
val hasPermission = for {
pushPermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).pushPermission
} yield {
pushPermission.toLowerCase match {
case "all" => true
case "moderator" => user.role == Roles.MODERATOR_ROLE
case "presenter" => user.presenter
case _ => false
}
}

if (!hasPermission.contains(true)) {
println(s"No permission to write in plugin: '${msg.body.pluginName}', data channel: '${msg.body.channelName}'.")
} else {
PluginDataChannelEntryDAO.insert(
meetingId,
msg.body.pluginName,
msg.body.channelName,
msg.body.subChannelName,
msg.header.userId,
msg.body.payloadJson,
msg.body.toRoles,
msg.body.toUserIds
)
}
PluginDataChannelEntryDAO.insert(
meetingId,
msg.body.pluginName,
msg.body.channelName,
msg.body.subChannelName,
msg.header.userId,
msg.body.payloadJson,
msg.body.toRoles,
msg.body.toUserIds
)
}
}
})
}
}
Loading

0 comments on commit cac5d72

Please sign in to comment.