Merge branch 'bbb-2x-mconf' of github.com:bigbluebutton/bigbluebutton into pods_vol1

This commit is contained in:
Anton Georgiev 2017-09-19 17:15:16 -04:00
commit 5a08c0cfca
338 changed files with 5986 additions and 1224 deletions

View File

@ -256,6 +256,14 @@ package org.bigbluebutton.modules.layout.managers
var newLayout:LayoutDefinition = _layoutModel.getLayout(name); var newLayout:LayoutDefinition = _layoutModel.getLayout(name);
if (newLayout == null) return; if (newLayout == null) return;
var logData:Object = UsersUtil.initLogData();
logData.reason = "Layout changed.";
logData.tags = ["layout"];
logData.message = "The layout was changed.";
logData.oldLayout = _currentLayout.name;
logData.newLayout = newLayout.name;
LOGGER.info(JSON.stringify(logData));
//trace(LOG + " applying layout [" + newLayout.name + "] to windows."); //trace(LOG + " applying layout [" + newLayout.name + "] to windows.");
applyLayout(newLayout); applyLayout(newLayout);
} }

View File

@ -63,7 +63,7 @@
content: "\e91e"; content: "\e91e";
} }
.icon-bbb-rectangle_tool:before { .icon-bbb-rectangle_tool:before {
content: "\e92f"; content: "\e91f";
} }
.icon-bbb-text_tool:before { .icon-bbb-text_tool:before {
content: "\e920"; content: "\e920";

0
bigbluebutton-html5/imports/api/1.1/chat/index.js Executable file → Normal file
View File

View File

View File

0
bigbluebutton-html5/imports/api/1.1/cursor/index.js Executable file → Normal file
View File

View File

@ -0,0 +1,43 @@
import RedisPubSub from '/imports/startup/server/redis';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
// import { isAllowedTo } from '/imports/startup/server/userPermissions';
import Presentations from '/imports/api/1.1/presentations';
export default function publishCursorUpdate(credentials, coordinates) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toBBBApps.presentation;
const EVENT_NAME = 'send_cursor_update';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(coordinates, {
xPercent: Number,
yPercent: Number,
});
// if (!isAllowedTo('moveCursor', credentials)) {
// throw new Meteor.Error('not-allowed', `You are not allowed to move the Cursor`);
// }
const Presentation = Presentations.findOne({
meetingId,
'presentation.current': true,
});
if (!Presentation) {
throw new Meteor.Error(
'presentation-not-found', 'You need a presentation to be able to move the cursor');
}
const payload = {
x_percent: coordinates.xPercent,
meeting_id: meetingId,
y_percent: coordinates.yPercent,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
}

View File

0
bigbluebutton-html5/imports/api/1.1/deskshare/index.js Executable file → Normal file
View File

View File

View File

View File

0
bigbluebutton-html5/imports/api/1.1/meetings/index.js Executable file → Normal file
View File

View File

View File

0
bigbluebutton-html5/imports/api/1.1/shapes/index.js Executable file → Normal file
View File

View File

@ -1,4 +1,3 @@
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import clearShapesWhiteboard from '../modifiers/clearShapesWhiteboard'; import clearShapesWhiteboard from '../modifiers/clearShapesWhiteboard';

View File

@ -1,4 +1,3 @@
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import { inReplyToHTML5Client } from '/imports/api/common/server/helpers'; import { inReplyToHTML5Client } from '/imports/api/common/server/helpers';
import Shapes from './../../'; import Shapes from './../../';
@ -30,6 +29,4 @@ export default function handleWhiteboardGetReply({ payload }) {
const whiteboardId = shape.wb_id; const whiteboardId = shape.wb_id;
shapesAdded.push(addShape(meetingId, whiteboardId, shape)); shapesAdded.push(addShape(meetingId, whiteboardId, shape));
}); });
return shapesAdded;
} }

View File

@ -1,4 +1,3 @@
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import addShape from '../modifiers/addShape'; import addShape from '../modifiers/addShape';

View File

@ -1,4 +1,3 @@
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import removeShape from '../modifiers/removeShape'; import removeShape from '../modifiers/removeShape';

View File

@ -1,4 +1,6 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import sendAnnotation from './methods/sendAnnotation';
Meteor.methods({ Meteor.methods({
sendAnnotation,
}); });

View File

@ -0,0 +1,24 @@
import RedisPubSub from '/imports/startup/server/redis';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
export default function clearWhiteboard(credentials, whiteboardId) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toBBBApps.whiteboard;
const EVENT_NAME = 'clear_whiteboard_request';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(whiteboardId, String);
const payload = {
requester_id: requesterUserId,
meeting_id: meetingId,
whiteboard_id: whiteboardId,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
}

View File

@ -0,0 +1,23 @@
import RedisPubSub from '/imports/startup/server/redis';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger';
export default function sendAnnotation(credentials, payload) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toBBBApps.whiteboard;
const EVENT_NAME = 'send_whiteboard_annotation_request';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(payload, Object);
payload.annotation.id = `${requesterUserId}-${payload.annotation.id}`;
payload.requester_id = requesterUserId;
payload.meeting_id = meetingId;
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
}

View File

@ -0,0 +1,24 @@
import RedisPubSub from '/imports/startup/server/redis';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
export default function undoAnnotation(credentials, whiteboardId) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toBBBApps.whiteboard;
const EVENT_NAME = 'undo_whiteboard_request';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(whiteboardId, String);
const payload = {
requester_id: requesterUserId,
meeting_id: meetingId,
whiteboard_id: whiteboardId,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
}

View File

@ -1,6 +1,7 @@
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import Shapes from './../../';
import Logger from '/imports/startup/server/logger'; import Logger from '/imports/startup/server/logger';
import Shapes from './../../';
const SHAPE_TYPE_TEXT = 'text'; const SHAPE_TYPE_TEXT = 'text';
const SHAPE_TYPE_POLL_RESULT = 'poll_result'; const SHAPE_TYPE_POLL_RESULT = 'poll_result';
@ -26,6 +27,7 @@ export default function addShape(meetingId, whiteboardId, shape) {
'shape.shape.type': shape.shape.type, 'shape.shape.type': shape.shape.type,
'shape.shape.status': shape.shape.status, 'shape.shape.status': shape.shape.status,
}, },
$inc: { 'shape.shape.version': 1 },
}; };
const shapeType = shape.shape_type; const shapeType = shape.shape_type;
@ -49,6 +51,7 @@ export default function addShape(meetingId, whiteboardId, shape) {
case SHAPE_TYPE_POLL_RESULT: case SHAPE_TYPE_POLL_RESULT:
shape.shape.result = JSON.parse(shape.shape.result); shape.shape.result = JSON.parse(shape.shape.result);
break;
default: default:
modifier.$set = Object.assign(modifier.$set, { modifier.$set = Object.assign(modifier.$set, {

View File

@ -1,5 +1,5 @@
import Shapes from './../../';
import Logger from '/imports/startup/server/logger'; import Logger from '/imports/startup/server/logger';
import Shapes from './../../';
export default function clearShapes(meetingId) { export default function clearShapes(meetingId) {
if (meetingId) { if (meetingId) {

View File

@ -1,6 +1,6 @@
import Shapes from './../../';
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger';
import Shapes from './../../';
export default function clearShapesWhiteboard(meetingId, whiteboardId) { export default function clearShapesWhiteboard(meetingId, whiteboardId) {
check(meetingId, String); check(meetingId, String);

View File

@ -1,6 +1,6 @@
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import Shapes from './../../';
import Logger from '/imports/startup/server/logger'; import Logger from '/imports/startup/server/logger';
import Shapes from './../../';
export default function removeShape(meetingId, whiteboardId, shapeId) { export default function removeShape(meetingId, whiteboardId, shapeId) {
check(meetingId, String); check(meetingId, String);

View File

@ -1,8 +1,8 @@
import Shapes from './../';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger'; import Logger from '/imports/startup/server/logger';
import mapToAcl from '/imports/startup/mapToAcl'; import mapToAcl from '/imports/startup/mapToAcl';
import Shapes from './../';
function shapes(credentials) { function shapes(credentials) {
const { meetingId, requesterUserId, requesterToken } = credentials; const { meetingId, requesterUserId, requesterToken } = credentials;

0
bigbluebutton-html5/imports/api/1.1/slides/index.js Executable file → Normal file
View File

View File

@ -1,3 +1,4 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
Meteor.methods(); Meteor.methods({
});

0
bigbluebutton-html5/imports/api/1.1/users/index.js Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

@ -1,24 +1,16 @@
import _ from 'lodash'; import _ from 'lodash';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import Annotations from '/imports/api/2.0/annotations'; import clearAnnotations from '../modifiers/clearAnnotations';
import addAnnotation from '../modifiers/addAnnotation'; import addAnnotation from '../modifiers/addAnnotation';
import removeAnnotation from '../modifiers/removeAnnotation';
export default function handleWhiteboardAnnotations({ body }, meetingId) { export default function handleWhiteboardAnnotations({ body }, meetingId) {
check(meetingId, String); check(meetingId, String);
check(body, Object); check(body, Object);
const { annotations, whiteboardId } = body; const { annotations, whiteboardId } = body;
const annotationIds = annotations.map(a => a.id);
const annotationsToRemove = Annotations.find({
meetingId,
wbId: whiteboardId,
'annotationInfo.id': { $nin: annotationIds },
}).fetch();
_.each(annotationsToRemove, (annotation) => { check(whiteboardId, String);
removeAnnotation(meetingId, annotation.whiteboardId, annotation.annotationInfo.id); clearAnnotations(meetingId, whiteboardId);
});
const annotationsAdded = []; const annotationsAdded = [];
_.each(annotations, (annotation) => { _.each(annotations, (annotation) => {

View File

@ -3,9 +3,17 @@ import { check } from 'meteor/check';
import clearAnnotations from '../modifiers/clearAnnotations'; import clearAnnotations from '../modifiers/clearAnnotations';
export default function handleWhiteboardCleared({ body }, meetingId) { export default function handleWhiteboardCleared({ body }, meetingId) {
const whiteboardId = body.whiteboardId; check(body, {
userId: String,
whiteboardId: String,
fullClear: Boolean,
});
check(whiteboardId, String); const { whiteboardId, fullClear, userId } = body;
if (fullClear) {
return clearAnnotations(meetingId, whiteboardId); return clearAnnotations(meetingId, whiteboardId);
}
return clearAnnotations(meetingId, whiteboardId, userId);
} }

View File

@ -1,4 +1,10 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import mapToAcl from '/imports/startup/mapToAcl'; import undoAnnotation from './methods/undoAnnotation';
import clearWhiteboard from './methods/clearWhiteboard';
import sendAnnotation from './methods/sendAnnotation';
Meteor.methods(); Meteor.methods({
undoAnnotation,
clearWhiteboard,
sendAnnotation,
});

View File

@ -0,0 +1,31 @@
import Acl from '/imports/startup/acl';
import { getMultiUserStatus } from '/imports/api/common/server/helpers';
import RedisPubSub from '/imports/startup/server/redis2x';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
export default function clearWhiteboard(credentials, whiteboardId) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'ClearWhiteboardPubMsg';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(whiteboardId, String);
const allowed = Acl.can('methods.clearWhiteboard', credentials) || getMultiUserStatus(meetingId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to clear the whiteboard`,
);
}
const payload = {
whiteboardId,
};
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}

View File

@ -0,0 +1,56 @@
import Acl from '/imports/startup/acl';
import { getMultiUserStatus } from '/imports/api/common/server/helpers';
import RedisPubSub from '/imports/startup/server/redis2x';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import Annotations from '/imports/api/2.0/annotations';
function isLastMessage(annotation, userId) {
if (annotation.status === 'DRAW_END') {
const selector = {
id: annotation.id,
userId,
};
const _annotation = Annotations.findOne(selector);
return _annotation !== null;
}
return false;
}
export default function sendAnnotation(credentials, annotation) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'SendWhiteboardAnnotationPubMsg';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(annotation, Object);
// We allow messages to pass through in 3 cases:
// 1. When it's a standard message in presenter mode (Acl check)
// 2. When it's a standard message in multi-user mode (getMultUserStatus check)
// 3. When it's the last message, happens when the user is currently drawing
// and then slide/presentation changes, the user lost presenter rights,
// or multi-user whiteboard gets turned off
// So we allow the last "DRAW_END" message to pass through, to finish the shape.
const allowed = Acl.can('methods.sendAnnotation', credentials) ||
getMultiUserStatus(meetingId) ||
isLastMessage(annotation, requesterUserId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to send an annotation`,
);
}
const payload = {
annotation,
};
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}

View File

@ -0,0 +1,31 @@
import Acl from '/imports/startup/acl';
import { getMultiUserStatus } from '/imports/api/common/server/helpers';
import RedisPubSub from '/imports/startup/server/redis2x';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
export default function undoAnnotation(credentials, whiteboardId) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'UndoWhiteboardPubMsg';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(whiteboardId, String);
const allowed = Acl.can('methods.undoAnnotation', credentials) || getMultiUserStatus(meetingId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to undo the annotation`,
);
}
const payload = {
whiteboardId,
};
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}

View File

@ -1,4 +1,4 @@
import { Match, check } from 'meteor/check'; import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger'; import Logger from '/imports/startup/server/logger';
import Annotations from '/imports/api/2.0/annotations'; import Annotations from '/imports/api/2.0/annotations';
@ -8,50 +8,17 @@ const ANNOTATION_TYPE_PENCIL = 'pencil';
export default function addAnnotation(meetingId, whiteboardId, userId, annotation) { export default function addAnnotation(meetingId, whiteboardId, userId, annotation) {
check(meetingId, String); check(meetingId, String);
check(whiteboardId, String); check(whiteboardId, String);
check(annotation, { check(annotation, Object);
id: String,
status: String,
annotationType: String,
annotationInfo: {
x: Match.Maybe(Number), // Text Annotation Only.
y: Match.Maybe(Number), // Text Annotation Only.
text: Match.Maybe(String), // Text Annotation Only.
fontColor: Match.Maybe(Number), // Text Annotation Only.
calcedFontSize: Match.Maybe(Number), // Text Annotation Only.
textBoxWidth: Match.Maybe(Number), // Text Annotation Only.
textBoxHeight: Match.Maybe(Number), // Text Annotation Only.
fontSize: Match.Maybe(Number), // Text Annotation Only.
dataPoints: Match.Maybe(String), // Text Annotation Only.
color: Match.Maybe(Number), // Draw Annotation Only.
thickness: Match.Maybe(Number), // Draw Annotation Only.
transparency: Match.Maybe(Boolean), // Draw Annotation Only.
points: Match.Maybe([Number]), // Draw and Poll Annotation Only.
numResponders: Match.Maybe(Number), // Poll Only Annotation.
result: Match.Maybe([{
id: Number,
key: String,
numVotes: Number,
}]), // Poll Only Annotation.
numRespondents: Match.Maybe(Number), // Poll Only Annotation.
id: String,
whiteboardId: String,
status: String,
type: String,
commands: Match.Maybe([Number]),
},
wbId: String,
userId: String,
position: Number,
});
const { id, status, annotationType, annotationInfo, wbId, position } = annotation; const { id, status, annotationType, annotationInfo, wbId, position } = annotation;
const selector = { const selector = {
meetingId, meetingId,
id: annotation.id, id,
userId, userId,
}; };
// annotationInfo will be added to the modifier in switch below, depending on the situation
const modifier = { const modifier = {
$set: { $set: {
whiteboardId, whiteboardId,
@ -59,28 +26,38 @@ export default function addAnnotation(meetingId, whiteboardId, userId, annotatio
id, id,
status, status,
annotationType, annotationType,
annotationInfo,
wbId, wbId,
position, position,
}, },
$inc: { version: 1 },
}; };
const shapeType = annotation.annotationType; const shapeType = annotation.annotationType;
switch (shapeType) { switch (shapeType) {
case ANNOTATION_TYPE_TEXT: case ANNOTATION_TYPE_TEXT:
// Replace flash new lines to html5 new lines if it's text
modifier.$set.annotationInfo = annotationInfo;
modifier.$set.annotationInfo.text = annotation.annotationInfo.text.replace(/[\r]/g, '\n'); modifier.$set.annotationInfo.text = annotation.annotationInfo.text.replace(/[\r]/g, '\n');
break; break;
case ANNOTATION_TYPE_PENCIL: case ANNOTATION_TYPE_PENCIL:
// On the draw_end he send us all the points, we don't need to push, we can simple // In the pencil draw update we need to add a coordinate to the existing array
// set the new points. // And update te rest of the properties
if (annotation.status !== 'DRAW_END') { if (annotation.status === 'DRAW_UPDATE') {
// We don't want it to be update twice. modifier.$set['annotationInfo.color'] = annotationInfo.color;
delete modifier.$set.annotationInfo; modifier.$set['annotationInfo.thickness'] = annotationInfo.thickness;
modifier.$push = { 'annotationInfo.points': { $each: annotation.annotationInfo.points } }; modifier.$set['annotationInfo.id'] = annotationInfo.id;
modifier.$set['annotationInfo.whiteboardId'] = annotationInfo.whiteboardId;
modifier.$set['annotationInfo.status'] = annotationInfo.status;
modifier.$set['annotationInfo.transparency'] = annotationInfo.transparency;
modifier.$push = { 'annotationInfo.points': { $each: annotationInfo.points } };
break;
} }
modifier.$set.annotationInfo = annotationInfo;
break; break;
default: default:
modifier.$set.annotationInfo = annotationInfo;
break; break;
} }

View File

@ -1,12 +1,36 @@
import Annotations from '/imports/api/2.0/annotations'; import Annotations from '/imports/api/2.0/annotations';
import Logger from '/imports/startup/server/logger'; import Logger from '/imports/startup/server/logger';
export default function clearAnnotations(meetingId, whiteboardId) { export default function clearAnnotations(meetingId, whiteboardId, userId) {
if (meetingId && whiteboardId) { const selector = {};
return Annotations.remove({ meetingId, whiteboardId }, Logger.info(`Cleared Annotations from whiteboard ${whiteboardId} (${meetingId})`));
} else if (meetingId) { if (meetingId) {
return Annotations.remove({ meetingId }, Logger.info(`Cleared Annotations (${meetingId})`)); selector.meetingId = meetingId;
} }
return Annotations.remove({}, Logger.info('Cleared Annotations (all)')); if (whiteboardId) {
selector.whiteboardId = whiteboardId;
}
if (userId) {
selector.userId = userId;
}
const cb = (err) => {
if (err) {
return Logger.error(`Removing Shapes2x from collection: ${err}`);
}
if (!meetingId) {
return Logger.info('Cleared Annotations (all)');
}
if (userId) {
return Logger.info(`Removed Shapes2x for userId=${userId} where whiteboard=${whiteboardId}`);
}
return Logger.info(`Removed Shapes2x where whiteboard=${whiteboardId}`);
};
return Annotations.remove(selector, cb);
} }

View File

View File

0
bigbluebutton-html5/imports/api/2.0/bbb/index.js Executable file → Normal file
View File

0
bigbluebutton-html5/imports/api/2.0/chat/index.js Executable file → Normal file
View File

View File

@ -15,5 +15,5 @@ export default function clearPublicChatHistory(credentials) {
const payload = {}; const payload = {};
return RedisPubSub.publish(CHANNEL, eventName, meetingId, payload, { userId: requesterUserId }); return RedisPubSub.publishUserMessage(CHANNEL, eventName, meetingId, requesterUserId, payload);
} }

View File

@ -50,5 +50,5 @@ export default function sendChat(credentials, message) {
eventName = 'SendPublicMessagePubMsg'; eventName = 'SendPublicMessagePubMsg';
} }
return RedisPubSub.publish(CHANNEL, eventName, meetingId, { message: parsedMessage }, { userId: requesterUserId }); return RedisPubSub.publishUserMessage(CHANNEL, eventName, meetingId, requesterUserId, { message: parsedMessage });
} }

View File

0
bigbluebutton-html5/imports/api/2.0/cursor/index.js Executable file → Normal file
View File

View File

@ -1,4 +1,6 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import publishCursorUpdate from './methods/publishCursorUpdate';
Meteor.methods({ Meteor.methods({
publishCursorUpdate,
}); });

View File

@ -0,0 +1,31 @@
import { getMultiUserStatus } from '/imports/api/common/server/helpers';
import RedisPubSub from '/imports/startup/server/redis2x';
import Acl from '/imports/startup/acl';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
export default function publishCursorUpdate(credentials, payload) {
const REDIS_CONFIG = Meteor.settings.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'SendCursorPositionPubMsg';
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(payload, {
xPercent: Number,
yPercent: Number,
});
const allowed = Acl.can('methods.moveCursor', credentials) || getMultiUserStatus(meetingId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to move the cursor`,
);
}
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}

View File

0
bigbluebutton-html5/imports/api/2.0/meetings/index.js Executable file → Normal file
View File

View File

@ -1,6 +1,5 @@
import changeLockSettings from '../modifiers/changeLockSettings'; import changeLockSettings from '../modifiers/changeLockSettings';
export default function handleLockSettingsInMeeting({ body }, meetingId) { export default function handleLockSettingsInMeeting({ body }, meetingId) {
return changeLockSettings(meetingId, body); return changeLockSettings(meetingId, body);
} }

View File

@ -1,6 +1,5 @@
import changeUserLock from '../modifiers/changeUserLock'; import changeUserLock from '../modifiers/changeUserLock';
export default function handleLockSettingsInMeeting({ body }, meetingId) { export default function handleLockSettingsInMeeting({ body }, meetingId) {
return changeUserLock(meetingId, body); return changeUserLock(meetingId, body);
} }

View File

View File

@ -18,13 +18,7 @@ export default function endMeeting(credentials) {
userId: requesterUserId, userId: requesterUserId,
}; };
const header = {
meetingId,
name: EVENT_NAME,
userId: requesterUserId,
};
Logger.verbose(`Meeting '${meetingId}' is destroyed by '${requesterUserId}'`); Logger.verbose(`Meeting '${meetingId}' is destroyed by '${requesterUserId}'`);
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header); return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
} }

View File

@ -16,7 +16,7 @@ export default function changeLockSettings(meetingId, payload) {
}); });
const selector = { const selector = {
meetingId meetingId,
}; };
const modifier = { const modifier = {
@ -25,11 +25,15 @@ export default function changeLockSettings(meetingId, payload) {
}, },
}; };
const cb = (err) => { const cb = (err, numChanged) => {
if (err) { if (err) {
return Logger.error(`Changing meeting={${meetingId}} lock settings: ${err}`); return Logger.error(`Changing meeting={${meetingId}} lock settings: ${err}`);
} }
if (numChanged) {
return Logger.error(`Changed meeting={${meetingId}} updated lock settings`);
}
}; };
return Meetings.upsert(selector, modifier, cb); return Meetings.upsert(selector, modifier, cb);
}; }

View File

@ -27,4 +27,4 @@ export default function changeUserLock(meetingId, payload) {
}; };
return Users.upsert(selector, modifier, cb); return Users.upsert(selector, modifier, cb);
}; }

Some files were not shown because too many files have changed in this diff Show More