From 09b39a8d638a0e919a44a9e00d7e39b7625c2b38 Mon Sep 17 00:00:00 2001 From: Pedro Beschorner Marin <pedrobmarin@gmail.com> Date: Wed, 10 Feb 2021 12:24:24 -0300 Subject: [PATCH] Add extra pad validation Associate pads with meetings so session validation is restricted to the meeting's valid session tokens. Meteor will dispatch new redis events on shared notes and closed captions pads creation. This event will go through apps and reach web to populate a new meeting's pad collection that contains all valid pad id's for that session. Nginx will use this collection to check if the user's session token belongs to the pad's authorized users. Besides these modifications, an extra change will be needed at notes.nginx. Location /pad/p/ needs to change it's auth_request: from /bigbluebutton/connection/checkAuthorization; to /bigbluebutton/connection/validatePad; --- .../senders/ReceivedJsonMsgHandlerActor.scala | 4 +++ .../core/running/MeetingActor.scala | 6 ++++ .../pads/AddCaptionsPadsSysMsgHdlr.scala | 21 +++++++++++ .../handlers/pads/AddPadSysMsgHdlr.scala | 22 ++++++++++++ .../core2/message/senders/MsgBuilder.scala | 20 +++++++++++ .../common2/msgs/SystemMsgs.scala | 16 +++++++++ .../org/bigbluebutton/api/MeetingService.java | 36 +++++++++++++++++++ .../org/bigbluebutton/api/domain/Meeting.java | 20 +++++++++++ .../messaging/messages/AddCaptionsPads.java | 11 ++++++ .../api/messaging/messages/AddPad.java | 13 +++++++ .../bigbluebutton/api/util/ParamsUtil.java | 16 +++++++++ .../api2/bus/ReceivedJsonMsgHdlrActor.scala | 4 +++ .../api2/meeting/OldMeetingMsgHdlrActor.scala | 10 ++++++ .../server/methods/addCaptionsPads.js | 19 ++++++++++ .../api/captions/server/methods/addPad.js | 32 +++++++++++++++++ .../captions/server/methods/createCaptions.js | 4 +++ .../server/modifiers/updateReadOnlyPadId.js | 2 ++ .../imports/api/note/server/methods/addPad.js | 21 +++++++++++ .../api/note/server/modifiers/addNote.js | 2 ++ .../imports/ui/components/note/service.js | 2 ++ bigbluebutton-web/bbb-web.nginx | 8 +++++ .../org/bigbluebutton/web/UrlMappings.groovy | 4 --- .../controllers/ConnectionController.groovy | 21 +++++++++++ 23 files changed, 310 insertions(+), 4 deletions(-) create mode 100755 akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddCaptionsPadsSysMsgHdlr.scala create mode 100755 akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddPadSysMsgHdlr.scala create mode 100755 bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddCaptionsPads.java create mode 100755 bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddPad.java create mode 100644 bigbluebutton-html5/imports/api/captions/server/methods/addCaptionsPads.js create mode 100644 bigbluebutton-html5/imports/api/captions/server/methods/addPad.js create mode 100644 bigbluebutton-html5/imports/api/note/server/methods/addPad.js mode change 100644 => 100755 bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala index 91dbac6f96..a5cc4119b6 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala @@ -76,6 +76,10 @@ class ReceivedJsonMsgHandlerActor( routeGenericMsg[EjectUserFromMeetingSysMsg](envelope, jsonNode) case ValidateConnAuthTokenSysMsg.NAME => route[ValidateConnAuthTokenSysMsg](meetingManagerChannel, envelope, jsonNode) + case AddPadSysMsg.NAME => + routeGenericMsg[AddPadSysMsg](envelope, jsonNode) + case AddCaptionsPadsSysMsg.NAME => + routeGenericMsg[AddCaptionsPadsSysMsg](envelope, jsonNode) // Guests case GetGuestsWaitingApprovalReqMsg.NAME => diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala index b5b2fb22df..d9a666efaf 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala @@ -26,6 +26,7 @@ import org.bigbluebutton.core.models._ import org.bigbluebutton.core2.{ MeetingStatus2x, Permissions } import org.bigbluebutton.core2.message.handlers._ import org.bigbluebutton.core2.message.handlers.meeting._ +import org.bigbluebutton.core2.message.handlers.pads._ import org.bigbluebutton.common2.msgs._ import org.bigbluebutton.core.apps.breakout._ import org.bigbluebutton.core.apps.polls._ @@ -84,6 +85,8 @@ class MeetingActor( with SyncGetMeetingInfoRespMsgHdlr with ClientToServerLatencyTracerMsgHdlr with ValidateConnAuthTokenSysMsgHdlr + with AddPadSysMsgHdlr + with AddCaptionsPadsSysMsgHdlr with UserActivitySignCmdMsgHdlr { object CheckVoiceRecordingInternalMsg @@ -491,6 +494,9 @@ class MeetingActor( case m: ValidateConnAuthTokenSysMsg => handleValidateConnAuthTokenSysMsg(m) + case m: AddPadSysMsg => handleAddPadSysMsg(m) + case m: AddCaptionsPadsSysMsg => handleAddCaptionsPadsSysMsg(m) + case m: UserActivitySignCmdMsg => handleUserActivitySignCmdMsg(m) case _ => log.warning("***** Cannot handle " + msg.envelope.name) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddCaptionsPadsSysMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddCaptionsPadsSysMsgHdlr.scala new file mode 100755 index 0000000000..466f3a354f --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddCaptionsPadsSysMsgHdlr.scala @@ -0,0 +1,21 @@ +package org.bigbluebutton.core2.message.handlers.pads + +import org.bigbluebutton.common2.msgs._ +import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter } +import org.bigbluebutton.core2.message.senders.MsgBuilder + +trait AddCaptionsPadsSysMsgHdlr { + this: BaseMeetingActor => + + val liveMeeting: LiveMeeting + val outGW: OutMsgRouter + + def handleAddCaptionsPadsSysMsg(msg: AddCaptionsPadsSysMsg) { + val padIds = msg.body.padIds + val meetingId = liveMeeting.props.meetingProp.intId + + log.info(s"Handling add captions pads for meetingId=${meetingId}") + + outGW.send(MsgBuilder.buildAddCaptionsPadsEvtMsg(meetingId, padIds)) + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddPadSysMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddPadSysMsgHdlr.scala new file mode 100755 index 0000000000..e9a30313d1 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/pads/AddPadSysMsgHdlr.scala @@ -0,0 +1,22 @@ +package org.bigbluebutton.core2.message.handlers.pads + +import org.bigbluebutton.common2.msgs._ +import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter } +import org.bigbluebutton.core2.message.senders.MsgBuilder + +trait AddPadSysMsgHdlr { + this: BaseMeetingActor => + + val liveMeeting: LiveMeeting + val outGW: OutMsgRouter + + def handleAddPadSysMsg(msg: AddPadSysMsg) { + val padId = msg.body.padId + val readOnlyId = msg.body.readOnlyId + val meetingId = liveMeeting.props.meetingProp.intId + + log.info(s"Handling add padId=${padId} and readOnlyId=${readOnlyId} for meetingId=${meetingId}") + + outGW.send(MsgBuilder.buildAddPadEvtMsg(meetingId, padId, readOnlyId)) + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala index c24d64e29f..3f079333d7 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala @@ -83,6 +83,26 @@ object MsgBuilder { BbbCommonEnvCoreMsg(envelope, event) } + def buildAddPadEvtMsg(meetingId: String, padId: String, readOnlyId: String): BbbCommonEnvCoreMsg = { + val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka") + val envelope = BbbCoreEnvelope(AddPadEvtMsg.NAME, routing) + val header = BbbCoreHeaderWithMeetingId(AddPadEvtMsg.NAME, meetingId) + val body = AddPadEvtMsgBody(padId, readOnlyId) + val event = AddPadEvtMsg(header, body) + + BbbCommonEnvCoreMsg(envelope, event) + } + + def buildAddCaptionsPadsEvtMsg(meetingId: String, padIds: Array[String]): BbbCommonEnvCoreMsg = { + val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka") + val envelope = BbbCoreEnvelope(AddCaptionsPadsEvtMsg.NAME, routing) + val header = BbbCoreHeaderWithMeetingId(AddCaptionsPadsEvtMsg.NAME, meetingId) + val body = AddCaptionsPadsEvtMsgBody(padIds) + val event = AddCaptionsPadsEvtMsg(header, body) + + BbbCommonEnvCoreMsg(envelope, event) + } + def buildGetUsersMeetingRespMsg(meetingId: String, userId: String, webusers: Vector[WebUser]): BbbCommonEnvCoreMsg = { val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, userId) val envelope = BbbCoreEnvelope(GetUsersMeetingRespMsg.NAME, routing) diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/SystemMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/SystemMsgs.scala index 677c475b91..6f8023dfd3 100755 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/SystemMsgs.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/SystemMsgs.scala @@ -189,6 +189,22 @@ case class ValidateConnAuthTokenSysRespMsg( case class ValidateConnAuthTokenSysRespMsgBody(meetingId: String, userId: String, connId: String, authzed: Boolean, app: String) +object AddPadSysMsg { val NAME = "AddPadSysMsg" } +case class AddPadSysMsg(header: BbbClientMsgHeader, body: AddPadSysMsgBody) extends StandardMsg +case class AddPadSysMsgBody(padId: String, readOnlyId: String) + +object AddCaptionsPadsSysMsg { val NAME = "AddCaptionsPadsSysMsg" } +case class AddCaptionsPadsSysMsg(header: BbbClientMsgHeader, body: AddCaptionsPadsSysMsgBody) extends StandardMsg +case class AddCaptionsPadsSysMsgBody(padIds: Array[String]) + +object AddPadEvtMsg { val NAME = "AddPadEvtMsg" } +case class AddPadEvtMsg(header: BbbCoreHeaderWithMeetingId, body: AddPadEvtMsgBody) extends BbbCoreMsg +case class AddPadEvtMsgBody(padId: String, readOnlyId: String) + +object AddCaptionsPadsEvtMsg { val NAME = "AddCaptionsPadsEvtMsg" } +case class AddCaptionsPadsEvtMsg(header: BbbCoreHeaderWithMeetingId, body: AddCaptionsPadsEvtMsgBody) extends BbbCoreMsg +case class AddCaptionsPadsEvtMsgBody(padIds: Array[String]) + object PublishedRecordingSysMsg { val NAME = "PublishedRecordingSysMsg" } case class PublishedRecordingSysMsg(header: BbbCoreBaseHeader, body: PublishedRecordingSysMsgBody) extends BbbCoreMsg case class PublishedRecordingSysMsgBody(recordId: String) 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 adff3ac461..71d1367513 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 @@ -54,6 +54,8 @@ import org.bigbluebutton.api.messaging.converters.messages.EndMeetingMessage; import org.bigbluebutton.api.messaging.converters.messages.PublishedRecordingMessage; import org.bigbluebutton.api.messaging.converters.messages.UnpublishedRecordingMessage; import org.bigbluebutton.api.messaging.converters.messages.DeletedRecordingMessage; +import org.bigbluebutton.api.messaging.messages.AddPad; +import org.bigbluebutton.api.messaging.messages.AddCaptionsPads; import org.bigbluebutton.api.messaging.messages.CreateBreakoutRoom; import org.bigbluebutton.api.messaging.messages.CreateMeeting; import org.bigbluebutton.api.messaging.messages.EndMeeting; @@ -161,6 +163,20 @@ public class MeetingService implements MessageListener { } } + public Boolean isPadValid(String padId, String sessionToken) { + UserSession us = getUserSessionWithAuthToken(sessionToken); + if (us == null) return false; + + Meeting m = getMeeting(us.meetingID); + if (m == null) return false; + + if (m.hasPad(padId)) { + return true; + } else { + return false; + } + } + public UserSession getUserSessionWithUserId(String userId) { for (UserSession userSession : sessions.values()) { if (userSession.internalUserId.equals(userId)) { @@ -1051,6 +1067,10 @@ public class MeetingService implements MessageListener { processGuestPolicyChanged((GuestPolicyChanged) message); } else if (message instanceof RecordChapterBreak) { processRecordingChapterBreak((RecordChapterBreak) message); + } else if (message instanceof AddPad) { + processAddPad((AddPad) message); + } else if (message instanceof AddCaptionsPads) { + processAddCaptionsPads((AddCaptionsPads) message); } else if (message instanceof MakePresentationDownloadableMsg) { processMakePresentationDownloadableMsg((MakePresentationDownloadableMsg) message); } else if (message instanceof UpdateRecordingStatus) { @@ -1069,6 +1089,22 @@ public class MeetingService implements MessageListener { } } + public void processAddPad(AddPad msg) { + Meeting m = getMeeting(msg.meetingId); + if (m != null) { + m.addPad(msg.padId, msg.readOnlyId); + } + } + + public void processAddCaptionsPads(AddCaptionsPads msg) { + Meeting m = getMeeting(msg.meetingId); + if (m != null) { + for (String padId : msg.padIds) { + m.addPad(padId, "undefined"); + } + } + } + public void processRecordingChapterBreak(RecordChapterBreak msg) { recordingService.kickOffRecordingChapterBreak(msg.meetingId, msg.timestamp); } 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 a19b62d773..9f424916eb 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 @@ -69,6 +69,7 @@ public class Meeting { private String defaultConfigToken; private String guestPolicy = GuestPolicy.ASK_MODERATOR; private boolean userHasJoined = false; + private Map<String, String> pads; private Map<String, String> metadata; private Map<String, Object> userCustomData; private final ConcurrentMap<String, User> users; @@ -131,6 +132,13 @@ public class Meeting { allowDuplicateExtUserid = builder.allowDuplicateExtUserid; endWhenNoModerator = builder.endWhenNoModerator; + /* + * A pad is a pair of padId and readOnlyId that represents + * valid etherpads instances for this meeting. They can be: + * - shared notes + * - closed captions + */ + pads = new HashMap<>(); userCustomData = new HashMap<>(); users = new ConcurrentHashMap<>(); @@ -179,6 +187,10 @@ public class Meeting { return configs.remove(token); } + public Map<String, String> getPads() { + return pads; + } + public Map<String, String> getMetadata() { return metadata; } @@ -537,6 +549,14 @@ public class Meeting { return sum; } + public void addPad(String padId, String readOnlyId) { + pads.put(padId, readOnlyId); + } + + public Boolean hasPad(String id) { + return pads.containsKey(id) || pads.containsValue(id); + } + public void addUserCustomData(String userID, Map<String, String> data) { userCustomData.put(userID, data); } diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddCaptionsPads.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddCaptionsPads.java new file mode 100755 index 0000000000..3ccd1e10d7 --- /dev/null +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddCaptionsPads.java @@ -0,0 +1,11 @@ +package org.bigbluebutton.api.messaging.messages; + +public class AddCaptionsPads implements IMessage { + public final String meetingId; + public final String[] padIds; + + public AddCaptionsPads(String meetingId, String[] padIds) { + this.meetingId = meetingId; + this.padIds = padIds; + } +} diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddPad.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddPad.java new file mode 100755 index 0000000000..1f255acd7f --- /dev/null +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/AddPad.java @@ -0,0 +1,13 @@ +package org.bigbluebutton.api.messaging.messages; + +public class AddPad implements IMessage { + public final String meetingId; + public final String padId; + public final String readOnlyId; + + public AddPad(String meetingId, String padId, String readOnlyId) { + this.meetingId = meetingId; + this.padId = padId; + this.readOnlyId = readOnlyId; + } +} 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 d02927d1e0..9a4b3e9674 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 @@ -51,4 +51,20 @@ public class ParamsUtil { } return token; } + + public static String getPadId(String url) { + String padId = "undefined"; + try { + String decodedURL = URLDecoder.decode(url, "UTF-8"); + String[] splitURL = decodedURL.split("\\?"); + // If there is no query params, it's an invalid URL already + if (splitURL.length == 2) { + String[] params = splitURL[0].split("\\/"); + padId = params[params.length - 1]; + } + } catch (UnsupportedEncodingException e) { + log.error(e.toString()); + } + return padId; + } } diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala index c78d684342..7eb216f80f 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala @@ -94,6 +94,10 @@ class ReceivedJsonMsgHdlrActor(val msgFromAkkaAppsEventBus: MsgFromAkkaAppsEvent route[GuestsWaitingApprovedEvtMsg](envelope, jsonNode) case GuestPolicyChangedEvtMsg.NAME => route[GuestPolicyChangedEvtMsg](envelope, jsonNode) + case AddPadEvtMsg.NAME => + route[AddPadEvtMsg](envelope, jsonNode) + case AddCaptionsPadsEvtMsg.NAME => + route[AddCaptionsPadsEvtMsg](envelope, jsonNode) case RecordingChapterBreakSysMsg.NAME => route[RecordingChapterBreakSysMsg](envelope, jsonNode) case SetPresentationDownloadableEvtMsg.NAME => diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala index 8c70b881e6..a43fbcf516 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala @@ -39,6 +39,8 @@ class OldMeetingMsgHdlrActor(val olgMsgGW: OldMessageReceivedGW) case m: PresentationUploadTokenSysPubMsg => handlePresentationUploadTokenSysPubMsg(m) case m: GuestsWaitingApprovedEvtMsg => handleGuestsWaitingApprovedEvtMsg(m) case m: GuestPolicyChangedEvtMsg => handleGuestPolicyChangedEvtMsg(m) + case m: AddCaptionsPadsEvtMsg => handleAddCaptionsPadsEvtMsg(m) + case m: AddPadEvtMsg => handleAddPadEvtMsg(m) case m: RecordingChapterBreakSysMsg => handleRecordingChapterBreakSysMsg(m) case m: SetPresentationDownloadableEvtMsg => handleSetPresentationDownloadableEvtMsg(m) case m: RecordingStatusChangedEvtMsg => handleRecordingStatusChangedEvtMsg(m) @@ -50,6 +52,14 @@ class OldMeetingMsgHdlrActor(val olgMsgGW: OldMessageReceivedGW) olgMsgGW.handle(new GuestPolicyChanged(msg.header.meetingId, msg.body.policy)) } + def handleAddPadEvtMsg(msg: AddPadEvtMsg): Unit = { + olgMsgGW.handle(new AddPad(msg.header.meetingId, msg.body.padId, msg.body.readOnlyId)) + } + + def handleAddCaptionsPadsEvtMsg(msg: AddCaptionsPadsEvtMsg): Unit = { + olgMsgGW.handle(new AddCaptionsPads(msg.header.meetingId, msg.body.padIds)) + } + def handleRecordingChapterBreakSysMsg(msg: RecordingChapterBreakSysMsg): Unit = { olgMsgGW.handle(new RecordChapterBreak(msg.body.meetingId, msg.body.timestamp)) } diff --git a/bigbluebutton-html5/imports/api/captions/server/methods/addCaptionsPads.js b/bigbluebutton-html5/imports/api/captions/server/methods/addCaptionsPads.js new file mode 100644 index 0000000000..4ca15b07f1 --- /dev/null +++ b/bigbluebutton-html5/imports/api/captions/server/methods/addCaptionsPads.js @@ -0,0 +1,19 @@ +import RedisPubSub from '/imports/startup/server/redis'; +import Logger from '/imports/startup/server/logger'; +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; + +export default function addCaptionsPads(meetingId, padIds) { + const REDIS_CONFIG = Meteor.settings.private.redis; + const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; + const EVENT_NAME = 'AddCaptionsPadsSysMsg'; + + check(meetingId, String); + check(padIds, [String]); + + const payload = { + padIds, + }; + + return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, 'nodeJSapp', payload); +} diff --git a/bigbluebutton-html5/imports/api/captions/server/methods/addPad.js b/bigbluebutton-html5/imports/api/captions/server/methods/addPad.js new file mode 100644 index 0000000000..e9b6df837e --- /dev/null +++ b/bigbluebutton-html5/imports/api/captions/server/methods/addPad.js @@ -0,0 +1,32 @@ +import RedisPubSub from '/imports/startup/server/redis'; +import Captions from '/imports/api/captions'; +import Logger from '/imports/startup/server/logger'; +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; + +export default function addPad(padId, readOnlyId) { + const REDIS_CONFIG = Meteor.settings.private.redis; + const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; + const EVENT_NAME = 'AddPadSysMsg'; + + check(padId, String); + check(readOnlyId, String); + + const pad = Captions.findOne({ padId }); + + if (!pad) { + Logger.error(`Could not find closed captions pad ${padId}`); + return; + } + + const { meetingId } = pad; + + check(meetingId, String); + + const payload = { + padId, + readOnlyId, + }; + + return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, 'nodeJSapp', payload); +} diff --git a/bigbluebutton-html5/imports/api/captions/server/methods/createCaptions.js b/bigbluebutton-html5/imports/api/captions/server/methods/createCaptions.js index 24215b91c5..af29cb8c88 100644 --- a/bigbluebutton-html5/imports/api/captions/server/methods/createCaptions.js +++ b/bigbluebutton-html5/imports/api/captions/server/methods/createCaptions.js @@ -6,6 +6,7 @@ import { getLocalesURL, } from '/imports/api/captions/server/helpers'; import addCaption from '/imports/api/captions/server/modifiers/addCaption'; +import addCaptionsPads from '/imports/api/captions/server/methods/addCaptionsPads'; import axios from 'axios'; export default function createCaptions(meetingId) { @@ -27,10 +28,13 @@ export default function createCaptions(meetingId) { Logger.error(`Could not get locales info for ${meetingId} ${status}`); return; } + const padIds = []; const locales = response.data; locales.forEach((locale) => { const padId = generatePadId(meetingId, locale.locale); addCaption(meetingId, padId, locale); + padIds.push(padId); }); + addCaptionsPads(meetingId, padIds); }).catch(error => Logger.error(`Could not create captions for ${meetingId}: ${error}`)); } diff --git a/bigbluebutton-html5/imports/api/captions/server/modifiers/updateReadOnlyPadId.js b/bigbluebutton-html5/imports/api/captions/server/modifiers/updateReadOnlyPadId.js index 8fddb6f814..fffbadf204 100644 --- a/bigbluebutton-html5/imports/api/captions/server/modifiers/updateReadOnlyPadId.js +++ b/bigbluebutton-html5/imports/api/captions/server/modifiers/updateReadOnlyPadId.js @@ -1,6 +1,7 @@ import Captions from '/imports/api/captions'; import Logger from '/imports/startup/server/logger'; import { check } from 'meteor/check'; +import addPad from '/imports/api/captions/server/methods/addPad'; export default function updateReadOnlyPadId(padId, readOnlyPadId) { check(padId, String); @@ -20,6 +21,7 @@ export default function updateReadOnlyPadId(padId, readOnlyPadId) { const numberAffected = Captions.update(selector, modifier, { multi: true }); if (numberAffected) { + addPad(padId, readOnlyPadId); Logger.verbose('Captions: added readOnlyPadId', { padId, readOnlyPadId }); } } catch (err) { diff --git a/bigbluebutton-html5/imports/api/note/server/methods/addPad.js b/bigbluebutton-html5/imports/api/note/server/methods/addPad.js new file mode 100644 index 0000000000..45acbde783 --- /dev/null +++ b/bigbluebutton-html5/imports/api/note/server/methods/addPad.js @@ -0,0 +1,21 @@ +import RedisPubSub from '/imports/startup/server/redis'; +import Logger from '/imports/startup/server/logger'; +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; + +export default function addPad(meetingId, padId, readOnlyId) { + const REDIS_CONFIG = Meteor.settings.private.redis; + const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; + const EVENT_NAME = 'AddPadSysMsg'; + + check(meetingId, String); + check(padId, String); + check(readOnlyId, String); + + const payload = { + padId, + readOnlyId, + }; + + return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, 'nodeJSapp', payload); +} diff --git a/bigbluebutton-html5/imports/api/note/server/modifiers/addNote.js b/bigbluebutton-html5/imports/api/note/server/modifiers/addNote.js index a3f8ae2f63..15f8152b19 100644 --- a/bigbluebutton-html5/imports/api/note/server/modifiers/addNote.js +++ b/bigbluebutton-html5/imports/api/note/server/modifiers/addNote.js @@ -1,6 +1,7 @@ import { check } from 'meteor/check'; import Note from '/imports/api/note'; import Logger from '/imports/startup/server/logger'; +import addPad from '/imports/api/note/server/methods/addPad'; export default function addNote(meetingId, noteId, readOnlyNoteId) { check(meetingId, String); @@ -23,6 +24,7 @@ export default function addNote(meetingId, noteId, readOnlyNoteId) { const { insertedId } = Note.upsert(selector, modifier); if (insertedId) { + addPad(meetingId, noteId, readOnlyNoteId); Logger.info(`Added note id=${noteId} readOnlyId=${readOnlyNoteId} meeting=${meetingId}`); } else { Logger.info(`Upserted note id=${noteId} readOnlyId=${readOnlyNoteId} meeting=${meetingId}`); diff --git a/bigbluebutton-html5/imports/ui/components/note/service.js b/bigbluebutton-html5/imports/ui/components/note/service.js index 1a6ee84ea1..6920998cee 100644 --- a/bigbluebutton-html5/imports/ui/components/note/service.js +++ b/bigbluebutton-html5/imports/ui/components/note/service.js @@ -25,6 +25,8 @@ const getLang = () => { const getNoteParams = () => { let config = {}; + const User = Users.findOne({ userId: Auth.userID }, { fields: { name: 1 } }); + config.userName = User.name; config.lang = getLang(); config.rtl = document.documentElement.getAttribute('dir') === 'rtl'; diff --git a/bigbluebutton-web/bbb-web.nginx b/bigbluebutton-web/bbb-web.nginx index 120d2dcf8a..57d34ebbe4 100755 --- a/bigbluebutton-web/bbb-web.nginx +++ b/bigbluebutton-web/bbb-web.nginx @@ -88,6 +88,14 @@ proxy_set_header X-Original-URI $request_uri; } + location = /bigbluebutton/connection/validatePad { + internal; + proxy_pass http://127.0.0.1:8090; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Original-URI $request_uri; + } + location ~ "^/bigbluebutton\/textTrack\/(?<textTrackToken>[a-zA-Z0-9]+)\/(?<recordId>[a-zA-Z0-9_-]+)\/(?<textTrack>.+)$" { # Workaround IE refusal to set cookies in iframe add_header P3P 'CP="No P3P policy available"'; diff --git a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/UrlMappings.groovy b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/UrlMappings.groovy index 10d573ce34..33a9343563 100755 --- a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/UrlMappings.groovy +++ b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/UrlMappings.groovy @@ -95,10 +95,6 @@ class UrlMappings { action = [POST: 'putRecordingTextTrack'] } - "/connection/checkAuthorization"(controller:"connection") { - action = [GET:'checkAuthorization'] - } - "/bigbluebutton/$controller/$action?/$id?(.${format})?" { constraints { // apply constraints here diff --git a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy old mode 100644 new mode 100755 index b55ccd7c55..4abb86651c --- a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy +++ b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy @@ -44,4 +44,25 @@ class ConnectionController { log.error("Error while authenticating connection.\n" + e.getMessage()) } } + + def validatePad = { + try { + String uri = request.getHeader("x-original-uri") + String sessionToken = ParamsUtil.getSessionToken(uri) + String padId = ParamsUtil.getPadId(uri) + Boolean valid = meetingService.isPadValid(padId, sessionToken) + + response.addHeader("Cache-Control", "no-cache") + response.contentType = 'plain/text' + if (valid) { + response.setStatus(200) + response.outputStream << 'authorized' + } else { + response.setStatus(401) + response.outputStream << 'unauthorized' + } + } catch (IOException e) { + log.error("Error while authenticating connection.\n" + e.getMessage()) + } + } } -- GitLab