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;
This commit is contained in:
parent
c0a7f9cd92
commit
09b39a8d63
@ -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 =>
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 =>
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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}`));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
@ -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}`);
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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"';
|
||||
|
@ -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
|
||||
|
21
bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy
Normal file → Executable file
21
bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ConnectionController.groovy
Normal file → Executable file
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user