bigbluebutton-Github/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js

187 lines
5.2 KiB
JavaScript
Raw Normal View History

2017-10-12 06:17:42 +08:00
import flat from 'flat';
2019-03-20 04:06:13 +08:00
import {
check,
Match,
} from 'meteor/check';
import SanitizeHTML from 'sanitize-html';
import Meetings, { RecordMeetings } from '/imports/api/meetings';
2016-10-22 00:27:47 +08:00
import Logger from '/imports/startup/server/logger';
import createNote from '/imports/api/note/server/methods/createNote';
import createCaptions from '/imports/api/captions/server/methods/createCaptions';
2019-10-23 09:26:25 +08:00
import { addAnnotationsStreamer } from '/imports/api/annotations/server/streamer';
2019-10-25 04:48:03 +08:00
import { addCursorStreamer } from '/imports/api/cursor/server/streamer';
import BannedUsers from '/imports/api/users/server/store/bannedUsers';
2016-10-22 00:27:47 +08:00
export default function addMeeting(meeting) {
2017-10-12 06:17:42 +08:00
const meetingId = meeting.meetingProp.intId;
2016-10-22 00:27:47 +08:00
check(meetingId, String);
2017-10-12 06:17:42 +08:00
check(meeting, {
breakoutProps: {
sequence: Number,
freeJoin: Boolean,
2017-10-12 06:17:42 +08:00
breakoutRooms: Array,
parentId: String,
2019-04-10 21:44:34 +08:00
enabled: Boolean,
record: Boolean,
privateChatEnabled: Boolean,
2017-10-12 06:17:42 +08:00
},
meetingProp: {
intId: String,
extId: String,
isBreakout: Boolean,
name: String,
},
usersProp: {
webcamsOnlyForModerator: Boolean,
guestPolicy: String,
maxUsers: Number,
allowModsToUnmuteUsers: Boolean,
2017-10-12 06:17:42 +08:00
},
durationProps: {
createdTime: Number,
duration: Number,
createdDate: String,
meetingExpireIfNoUserJoinedInMinutes: Number,
meetingExpireWhenLastUserLeftInMinutes: Number,
userInactivityInspectTimerInMinutes: Number,
userInactivityThresholdInMinutes: Number,
userActivitySignResponseDelayInMinutes: Number,
timeRemaining: Number,
2017-10-12 06:17:42 +08:00
},
welcomeProp: {
welcomeMsg: String,
modOnlyMessage: String,
welcomeMsgTemplate: String,
},
recordProp: Match.ObjectIncluding({
2017-10-12 06:17:42 +08:00
allowStartStopRecording: Boolean,
autoStartRecording: Boolean,
2019-02-20 06:29:23 +08:00
record: Boolean,
}),
2017-10-12 06:17:42 +08:00
password: {
viewerPass: String,
moderatorPass: String,
},
voiceProp: {
voiceConf: String,
dialNumber: String,
telVoice: String,
muteOnStart: Boolean,
2017-10-12 06:17:42 +08:00
},
screenshareProps: {
red5ScreenshareIp: String,
red5ScreenshareApp: String,
screenshareConf: String,
},
metadataProp: Object,
2019-04-10 21:44:34 +08:00
lockSettingsProps: {
disableCam: Boolean,
disableMic: Boolean,
disablePrivateChat: Boolean,
disablePublicChat: Boolean,
disableNote: Boolean,
hideUserList: Boolean,
2019-04-10 21:44:34 +08:00
lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean,
lockedLayout: Boolean,
},
systemProps: {
html5InstanceId: Number,
},
2017-10-12 06:17:42 +08:00
});
2016-10-22 00:27:47 +08:00
const {
recordProp,
...restProps
} = meeting;
const newMeeting = restProps;
2019-02-20 06:29:23 +08:00
2016-10-22 00:27:47 +08:00
const selector = {
2016-10-24 19:20:30 +08:00
meetingId,
2016-10-22 00:27:47 +08:00
};
2019-04-10 21:44:34 +08:00
newMeeting.lockSettingsProps = Object.assign(meeting.lockSettingsProps, { setBy: 'temp' });
2019-04-06 02:33:09 +08:00
const meetingEnded = false;
2019-03-20 04:06:13 +08:00
let { welcomeMsg } = newMeeting.welcomeProp;
const sanitizeTextInChat = original => SanitizeHTML(original, {
allowedTags: ['a', 'b', 'br', 'i', 'img', 'li', 'small', 'span', 'strong', 'u', 'ul'],
allowedAttributes: {
a: ['href', 'name', 'target'],
img: ['src', 'width', 'height'],
},
allowedSchemes: ['https'],
});
const sanitizedWelcomeText = sanitizeTextInChat(welcomeMsg);
welcomeMsg = sanitizedWelcomeText.replace(
2019-02-23 06:08:44 +08:00
'href="event:',
'href="',
);
2019-02-26 01:01:28 +08:00
const insertBlankTarget = (s, i) => `${s.substr(0, i)} target="_blank"${s.substr(i)}`;
const linkWithoutTarget = new RegExp('<a href="(.*?)">', 'g');
linkWithoutTarget.test(welcomeMsg);
2019-02-26 01:01:28 +08:00
if (linkWithoutTarget.lastIndex > 0) {
welcomeMsg = insertBlankTarget(
welcomeMsg,
2019-02-26 01:01:28 +08:00
linkWithoutTarget.lastIndex - 1,
);
}
2019-02-20 06:29:23 +08:00
newMeeting.welcomeProp.welcomeMsg = welcomeMsg;
// note: as of July 2020 `modOnlyMessage` is not published to the client side.
// We are sanitizing this data simply to prevent future potential usage
// At the moment `modOnlyMessage` is obtained from client side as a response to Enter API
newMeeting.welcomeProp.modOnlyMessage = sanitizeTextInChat(newMeeting.welcomeProp.modOnlyMessage);
2016-10-22 00:27:47 +08:00
const modifier = {
2019-03-20 04:06:13 +08:00
$set: Object.assign({
meetingId,
2019-04-06 02:33:09 +08:00
meetingEnded,
publishedPoll: false,
randomlySelectedUser: '',
2019-03-20 04:06:13 +08:00
}, flat(newMeeting, {
safe: true,
2019-04-06 02:33:09 +08:00
})),
2016-10-22 00:27:47 +08:00
};
try {
const { insertedId, numberAffected } = RecordMeetings.upsert(selector, { meetingId, ...recordProp });
if (insertedId) {
Logger.info(`Added record prop id=${meetingId}`);
} else if (numberAffected) {
Logger.info(`Upserted record prop id=${meetingId}`);
2016-10-22 00:27:47 +08:00
}
} catch (err) {
Logger.error(`Adding record prop to collection: ${err}`);
}
try {
const { insertedId, numberAffected } = Meetings.upsert(selector, modifier);
2016-10-22 00:27:47 +08:00
addAnnotationsStreamer(meetingId);
addCursorStreamer(meetingId);
2019-03-20 04:06:13 +08:00
2016-10-22 00:27:47 +08:00
if (insertedId) {
Logger.info(`Added meeting id=${meetingId}`);
// TODO: Here we call Etherpad API to create this meeting notes. Is there a
// better place we can run this post-creation routine?
createNote(meetingId);
createCaptions(meetingId);
BannedUsers.init(meetingId);
} else if (numberAffected) {
Logger.info(`Upserted meeting id=${meetingId}`);
2016-10-22 00:27:47 +08:00
}
} catch (err) {
Logger.error(`Adding meeting to collection: ${err}`);
}
2017-06-03 03:25:02 +08:00
}