Remove: meeting meteor server files

This commit is contained in:
Tainan Felipe 2024-04-25 17:58:24 -03:00
parent 7096620781
commit 304838f213
31 changed files with 0 additions and 841 deletions

View File

@ -1,3 +0,0 @@
import EventEmitter from 'events';
export default new EventEmitter();

View File

@ -1,34 +0,0 @@
import RedisPubSub from '/imports/startup/server/redis';
import handleMeetingCreation from './handlers/meetingCreation';
import handleGetAllMeetings from './handlers/getAllMeetings';
import handleMeetingEnd from './handlers/meetingEnd';
import handleMeetingDestruction from './handlers/meetingDestruction';
import handleMeetingLocksChange from './handlers/meetingLockChange';
import handleGuestPolicyChanged from './handlers/guestPolicyChanged';
import handleGuestLobbyMessageChanged from './handlers/guestLobbyMessageChanged';
import handleUserLockChange from './handlers/userLockChange';
import handleTimeRemainingUpdate from './handlers/timeRemainingUpdate';
import handleChangeWebcamOnlyModerator from './handlers/webcamOnlyModerator';
import handleBroadcastLayout from './handlers/broadcastLayout';
import handleNotifyAllInMeetingEvtMsg from './handlers/handleNotifyAllInMeetingEvtMsg';
import handleNotifyUserInMeeting from './handlers/handleNotifyUserInMeeting';
import handleNotifyRoleInMeeting from './handlers/handleNotifyRoleInMeeting';
import handleBroadcastPushLayout from './handlers/broadcastPushLayout';
RedisPubSub.on('MeetingCreatedEvtMsg', handleMeetingCreation);
RedisPubSub.on('SyncGetMeetingInfoRespMsg', handleGetAllMeetings);
RedisPubSub.on('MeetingEndingEvtMsg', handleMeetingEnd);
RedisPubSub.on('MeetingDestroyedEvtMsg', handleMeetingDestruction);
RedisPubSub.on('LockSettingsInMeetingChangedEvtMsg', handleMeetingLocksChange);
RedisPubSub.on('UserLockedInMeetingEvtMsg', handleUserLockChange);
RedisPubSub.on('WebcamsOnlyForModeratorChangedEvtMsg', handleChangeWebcamOnlyModerator);
RedisPubSub.on('GetLockSettingsRespMsg', handleMeetingLocksChange);
RedisPubSub.on('GuestPolicyChangedEvtMsg', handleGuestPolicyChanged);
RedisPubSub.on('GuestLobbyMessageChangedEvtMsg', handleGuestLobbyMessageChanged);
RedisPubSub.on('MeetingTimeRemainingUpdateEvtMsg', handleTimeRemainingUpdate);
RedisPubSub.on('BroadcastLayoutEvtMsg', handleBroadcastLayout);
RedisPubSub.on('NotifyAllInMeetingEvtMsg', handleNotifyAllInMeetingEvtMsg);
RedisPubSub.on('NotifyUserInMeetingEvtMsg', handleNotifyUserInMeeting);
RedisPubSub.on('NotifyRoleInMeetingEvtMsg', handleNotifyRoleInMeeting);
RedisPubSub.on('BroadcastPushLayoutEvtMsg', handleBroadcastPushLayout);

View File

@ -1,27 +0,0 @@
import changeLayout from '../modifiers/changeLayout';
export default async function broadcastLayout({ body }, meetingId) {
const {
layout,
presentationIsOpen,
isResizing,
cameraPosition,
focusedCamera,
presentationVideoRate,
pushLayout,
setByUserId,
} = body;
const result = await changeLayout(
meetingId,
layout,
presentationIsOpen,
isResizing,
cameraPosition,
focusedCamera,
presentationVideoRate,
pushLayout,
setByUserId,
);
return result;
}

View File

@ -1,8 +0,0 @@
import setPushLayout from '../modifiers/setPushLayout';
export default async function broadcastPushLayout({ body }, meetingId) {
const { pushLayout, setByUserId } = body;
const result = await setPushLayout(meetingId, pushLayout, setByUserId);
return result;
}

View File

@ -1,6 +0,0 @@
import handleMeetingCreation from './meetingCreation';
export default async function handleGetAllMeetings({ body }) {
const result = await handleMeetingCreation({ body });
return result;
}

View File

@ -1,11 +0,0 @@
import { check } from 'meteor/check';
import setGuestLobbyMessage from '../modifiers/setGuestLobbyMessage';
export default async function handleGuestLobbyMessageChanged({ body }, meetingId) {
const { message } = body;
check(meetingId, String);
check(message, String);
const result = await setGuestLobbyMessage(meetingId, message);
return result;
}

View File

@ -1,12 +0,0 @@
import { check } from 'meteor/check';
import setGuestPolicy from '../modifiers/setGuestPolicy';
export default async function handleGuestPolicyChanged({ body }, meetingId) {
const { policy } = body;
check(meetingId, String);
check(policy, String);
const result = await setGuestPolicy(meetingId, policy);
return result;
}

View File

@ -1,14 +0,0 @@
import { check } from 'meteor/check';
import emitNotification from '/imports/api/meetings/server/modifiers/emitNotification';
export default function handleNotifyAllInMeeting({ body }) {
check(body, {
meetingId: String,
notificationType: String,
icon: String,
messageId: String,
messageDescription: String,
messageValues: Array,
});
return emitNotification(body, 'notifyAllInMeeting');
}

View File

@ -1,15 +0,0 @@
import { check } from 'meteor/check';
import emitNotification from '/imports/api/meetings/server/modifiers/emitNotification';
export default function handleNotifyRoleInMeeting({ body }) {
check(body, {
role: String,
meetingId: String,
notificationType: String,
icon: String,
messageId: String,
messageDescription: String,
messageValues: Array,
});
return emitNotification(body, 'NotifyRoleInMeeting');
}

View File

@ -1,15 +0,0 @@
import { check } from 'meteor/check';
import emitNotification from '/imports/api/meetings/server/modifiers/emitNotification';
export default function handleNotifyUserInMeeting({ body }) {
check(body, {
userId: String,
meetingId: String,
notificationType: String,
icon: String,
messageId: String,
messageDescription: String,
messageValues: Array,
});
return emitNotification(body, 'NotifyUserInMeeting');
}

View File

@ -1,11 +0,0 @@
import { check } from 'meteor/check';
import addMeeting from '../modifiers/addMeeting';
export default async function handleMeetingCreation({ body }) {
const meeting = body.props;
const durationInSecods = (meeting.durationProps.duration * 60);
meeting.durationProps.timeRemaining = durationInSecods;
check(meeting, Object);
const result = await addMeeting(meeting);
return result;
}

View File

@ -1,12 +0,0 @@
import RedisPubSub from '/imports/startup/server/redis';
import { check } from 'meteor/check';
export default function handleMeetingDestruction({ body }) {
check(body, Object);
const { meetingId } = body;
check(meetingId, String);
return RedisPubSub.destroyMeetingQueue(meetingId);
}

View File

@ -1,56 +0,0 @@
import { check } from 'meteor/check';
import meetingHasEnded from '../modifiers/meetingHasEnded';
import Meetings from '/imports/api/meetings';
import Breakouts from '/imports/api/breakouts';
import Logger from '/imports/startup/server/logger';
export default async function handleMeetingEnd({ header, body }) {
check(body, Object);
const { meetingId, reason } = body;
check(meetingId, String);
check(header, Object);
const { userId } = header;
check(userId, String);
const cb = (err, num, meetingType) => {
if (err) {
Logger.error(`${meetingType} ending error: ${err}`);
return;
}
if (num) {
Meteor.setTimeout(() => { meetingHasEnded(meetingId); }, 10000);
}
};
await Meetings.find({ meetingId }).forEachAsync(async (doc) => {
let num = 0;
let err = null;
try {
num = await Meetings.updateAsync({ meetingId },
{
$set: {
meetingEnded: true,
meetingEndedBy: userId,
meetingEndedReason: reason,
learningDashboardAccessToken: doc.password.learningDashboardAccessToken,
},
});
} catch (error) {
err = error;
}
cb(err, num, 'Meeting');
});
let num = 0;
let err = null;
try {
num = await Breakouts.update(
{ parentMeetingId: meetingId },
{ $set: { meetingEnded: true } },
);
} catch (error) {
err = error;
}
cb(err, num, 'Breakout');
}

View File

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

View File

@ -1,28 +0,0 @@
import { check } from 'meteor/check';
import { MeetingTimeRemaining } from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
export default async function handleTimeRemainingUpdate({ body }, meetingId) {
check(meetingId, String);
check(body, {
timeLeftInSec: Number,
});
const { timeLeftInSec } = body;
const selector = {
meetingId,
};
const modifier = {
$set: {
timeRemaining: timeLeftInSec,
},
};
try {
await MeetingTimeRemaining.upsertAsync(selector, modifier);
} catch (err) {
Logger.error(`Changing recording time: ${err}`);
}
}

View File

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

View File

@ -1,5 +0,0 @@
import changeWebcamOnlyModerator from '../modifiers/webcamOnlyModerator';
export default async function handleChangeWebcamOnlyModerator({ body }, meetingId) {
await changeWebcamOnlyModerator(meetingId, body);
}

View File

@ -1 +0,0 @@
import './eventHandlers';

View File

@ -1,223 +0,0 @@
import flat from 'flat';
import {
check,
Match,
} from 'meteor/check';
import SanitizeHTML from 'sanitize-html';
import Meetings, {
LayoutMeetings,
} from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
import { LAYOUT_TYPE } from '/imports/ui/components/layout/enums';
const addLayout = async (meetingId, layout) => {
const selector = { meetingId };
const modifier = {
meetingId,
layout,
layoutUpdatedAt: new Date().getTime(),
presentationIsOpen: true,
isResizing: false,
cameraPosition: 'contentTop',
focusedCamera: 'none',
presentationVideoRate: 0,
pushLayout: false,
};
try {
const { numberAffected } = await LayoutMeetings.upsertAsync(selector, modifier);
if (numberAffected) {
Logger.verbose(`Added layout meetingId=${meetingId}`, numberAffected);
}
} catch (err) {
Logger.error(`Adding layout: ${err}`);
}
};
export default async function addMeeting(meeting) {
const meetingId = meeting.meetingProp.intId;
check(meetingId, String);
check(meeting, {
breakoutProps: {
sequence: Number,
freeJoin: Boolean,
breakoutRooms: Array,
parentId: String,
record: Boolean,
privateChatEnabled: Boolean,
captureNotes: Boolean,
captureSlides: Boolean,
captureNotesFilename: String,
captureSlidesFilename: String,
},
meetingProp: {
intId: String,
extId: String,
meetingCameraCap: Number,
maxPinnedCameras: Number,
isBreakout: Boolean,
name: String,
disabledFeatures: Array,
notifyRecordingIsOn: Boolean,
presentationUploadExternalDescription: String,
presentationUploadExternalUrl: String,
},
usersProp: {
maxUsers: Number,
maxUserConcurrentAccesses: Number,
webcamsOnlyForModerator: Boolean,
userCameraCap: Number,
guestPolicy: String,
authenticatedGuest: Boolean,
allowModsToUnmuteUsers: Boolean,
allowModsToEjectCameras: Boolean,
meetingLayout: String,
},
durationProps: {
createdTime: Number,
duration: Number,
createdDate: String,
meetingExpireIfNoUserJoinedInMinutes: Number,
meetingExpireWhenLastUserLeftInMinutes: Number,
userInactivityInspectTimerInMinutes: Number,
userInactivityThresholdInMinutes: Number,
userActivitySignResponseDelayInMinutes: Number,
endWhenNoModerator: Boolean,
endWhenNoModeratorDelayInMinutes: Number,
timeRemaining: Number,
},
welcomeProp: {
welcomeMsg: String,
modOnlyMessage: String,
welcomeMsgTemplate: String,
},
recordProp: Match.ObjectIncluding({
allowStartStopRecording: Boolean,
autoStartRecording: Boolean,
record: Boolean,
}),
password: {
viewerPass: String,
moderatorPass: String,
learningDashboardAccessToken: String,
},
voiceProp: {
voiceConf: String,
dialNumber: String,
telVoice: String,
muteOnStart: Boolean,
},
metadataProp: Object,
lockSettingsProps: {
disableCam: Boolean,
disableMic: Boolean,
disablePrivateChat: Boolean,
disablePublicChat: Boolean,
disableNotes: Boolean,
hideUserList: Boolean,
lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean,
hideViewersCursor: Boolean,
hideViewersAnnotation: Boolean,
},
systemProps: {
html5InstanceId: Number,
loginUrl: String,
logoutUrl: String,
customLogoURL: String,
bannerText: String,
bannerColor: String,
},
groups: Array,
overrideClientSettings: String,
});
const {
recordProp,
...restProps
} = meeting;
const newMeeting = restProps;
const selector = {
meetingId,
};
newMeeting.lockSettingsProps = Object.assign(meeting.lockSettingsProps, { setBy: 'temp' });
const meetingEnded = false;
let { welcomeMsg } = newMeeting.welcomeProp;
const sanitizeTextInChat = (original) => SanitizeHTML(original, {
allowedTags: ['a', 'b', 'br', 'i', 'img', 'li', 'small', 'span', 'strong', 'u', 'ul'],
allowedAttributes: {
a: ['href', 'target'],
img: ['src', 'width', 'height'],
},
allowedSchemes: ['https'],
allowedSchemesByTag: {
a: ['https', 'mailto', 'tel'],
},
});
const sanitizedWelcomeText = sanitizeTextInChat(welcomeMsg);
welcomeMsg = sanitizedWelcomeText.replace(
'href="event:',
'href="',
);
const insertBlankTarget = (s, i) => `${s.substr(0, i)} target="_blank"${s.substr(i)}`;
const linkWithoutTarget = new RegExp('<a href="(.*?)">', 'g');
do {
linkWithoutTarget.test(welcomeMsg);
if (linkWithoutTarget.lastIndex > 0) {
welcomeMsg = insertBlankTarget(
welcomeMsg,
linkWithoutTarget.lastIndex - 1,
);
linkWithoutTarget.lastIndex -= 1;
}
} while (linkWithoutTarget.lastIndex > 0);
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);
const { meetingLayout } = meeting.usersProp;
const modifier = {
$set: {
meetingId,
meetingEnded,
layout: LAYOUT_TYPE[meetingLayout] || 'smart',
publishedPoll: false,
guestLobbyMessage: '',
...flat(newMeeting, {
safe: true,
}),
},
};
await addLayout(meetingId, LAYOUT_TYPE[meetingLayout] || 'smart');
try {
const { insertedId, numberAffected } = await Meetings.upsertAsync(selector, modifier);
if (insertedId) {
Logger.info(`Added meeting id=${meetingId}`);
} else if (numberAffected) {
Logger.info(`Upserted meeting id=${meetingId}`);
}
} catch (err) {
Logger.error(`Adding meeting to collection: ${err}`);
}
}

View File

@ -1,48 +0,0 @@
import Logger from '/imports/startup/server/logger';
import { LayoutMeetings } from '/imports/api/meetings';
import { check } from 'meteor/check';
import { LAYOUT_TYPE } from '/imports/ui/components/layout/enums';
export default async function changeLayout(
meetingId,
layout,
presentationIsOpen,
isResizing,
cameraPosition,
focusedCamera,
presentationVideoRate,
pushLayout,
requesterUserId,
) {
try {
check(meetingId, String);
check(requesterUserId, String);
check(isResizing, Boolean);
check(layout, String);
const selector = {
meetingId,
};
const modifier = {
$set: {
layout: LAYOUT_TYPE[layout] || LAYOUT_TYPE.SMART_LAYOUT,
layoutUpdatedAt: new Date().getTime(),
presentationIsOpen,
isResizing,
cameraPosition,
focusedCamera,
presentationVideoRate,
pushLayout,
},
};
const numberAffected = LayoutMeetings.updateAsync(selector, modifier);
if (numberAffected) {
Logger.info(`MeetingLayout changed to ${layout} for meeting=${meetingId} requested by user=${requesterUserId}`);
}
} catch (err) {
Logger.error(`Exception while invoking method changeLayout ${err.stack}`);
}
}

View File

@ -1,67 +0,0 @@
import Logger from '/imports/startup/server/logger';
import Meetings from '/imports/api/meetings';
import { check } from 'meteor/check';
export default async function changeLockSettings(meetingId, payload) {
check(meetingId, String);
check(payload, {
disableCam: Boolean,
disableMic: Boolean,
disablePrivChat: Boolean,
disablePubChat: Boolean,
disableNotes: Boolean,
hideUserList: Boolean,
lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean,
hideViewersCursor: Boolean,
hideViewersAnnotation: Boolean,
setBy: Match.Maybe(String),
});
const {
disableCam,
disableMic,
disablePrivChat,
disablePubChat,
disableNotes,
hideUserList,
lockOnJoin,
lockOnJoinConfigurable,
hideViewersCursor,
hideViewersAnnotation,
setBy,
} = payload;
const selector = {
meetingId,
};
const modifier = {
$set: {
lockSettingsProps: {
disableCam,
disableMic,
disablePrivateChat: disablePrivChat,
disablePublicChat: disablePubChat,
disableNotes,
hideUserList,
lockOnJoin,
lockOnJoinConfigurable,
hideViewersCursor,
hideViewersAnnotation,
setBy,
},
},
};
try {
const { numberAffected } = await Meetings.upsertAsync(selector, modifier);
if (numberAffected) {
Logger.info(`Changed meeting={${meetingId}} updated lock settings`);
} else {
Logger.info(`meeting={${meetingId}} lock settings were not updated`);
}
} catch (err) {
Logger.error(`Changing meeting={${meetingId}} lock settings: ${err}`);
}
}

View File

@ -1,37 +0,0 @@
import Logger from '/imports/startup/server/logger';
import Users from '/imports/api/users';
import { check } from 'meteor/check';
export default async function changeUserLock(meetingId, payload) {
check(meetingId, String);
check(payload, {
userId: String,
locked: Boolean,
lockedBy: String,
});
const { userId, locked, lockedBy } = payload;
const selector = {
meetingId,
userId,
};
const modifier = {
$set: {
locked,
},
};
try {
const { numberAffected } = Users.updateAsync(selector, modifier);
if (numberAffected) {
Logger.info(`User's userId=${userId} lock status was changed to: ${locked} by user userId=${lockedBy}`);
} else {
Logger.info(`User's userId=${userId} lock status wasn't updated`);
}
} catch (err) {
Logger.error(`Changing user lock setting: ${err}`);
}
}

View File

@ -1,26 +0,0 @@
import { MeetingTimeRemaining } from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
export default async function clearMeetingTimeRemaining(meetingId) {
if (meetingId) {
try {
const numberAffected = await MeetingTimeRemaining.removeAsync({ meetingId });
if (numberAffected) {
Logger.info(`Cleared MeetingTimeRemaining in (${meetingId})`);
}
} catch (err) {
Logger.info(`Error on clearing MeetingTimeRemaining in (${meetingId}). ${err}`);
}
} else {
try {
const numberAffected = await MeetingTimeRemaining.removeAsync({});
if (numberAffected) {
Logger.info('Cleared MeetingTimeRemaining in all meetings');
}
} catch (err) {
Logger.error(`Error on clearing MeetingTimeRemaining in all meetings. ${err}`);
}
}
}

View File

@ -1,10 +0,0 @@
import notificationEmitter from '../../notificationEmitter';
export default function emitNotification(body, type) {
if (!process.env.BBB_HTML5_ROLE || (process.env.BBB_HTML5_ROLE === 'frontend')) {
notificationEmitter.emit('notification', {
type,
...body,
});
}
}

View File

@ -1,14 +0,0 @@
import Meetings from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
import clearMeetingTimeRemaining from '/imports/api/meetings/server/modifiers/clearMeetingTimeRemaining';
import Metrics from '/imports/startup/server/metrics';
export default async function meetingHasEnded(meetingId) {
await Meetings.removeAsync({ meetingId });
await Promise.all([
clearMeetingTimeRemaining(meetingId),
]);
await Metrics.removeMeeting(meetingId);
return Logger.info(`Cleared Meetings with id ${meetingId}`);
}

View File

@ -1,28 +0,0 @@
import Meetings from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check';
export default async function setGuestLobbyMessage(meetingId, guestLobbyMessage) {
check(meetingId, String);
check(guestLobbyMessage, String);
const selector = {
meetingId,
};
const modifier = {
$set: {
guestLobbyMessage,
},
};
try {
const { numberAffected } = await Meetings.upsertAsync(selector, modifier);
if (numberAffected) {
Logger.verbose(`Set guest lobby message meetingId=${meetingId} guestLobbyMessage=${guestLobbyMessage}`);
}
} catch (err) {
Logger.error(`Setting guest lobby message: ${err}`);
}
}

View File

@ -1,28 +0,0 @@
import Meetings from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check';
export default async function setGuestPolicy(meetingId, guestPolicy) {
check(meetingId, String);
check(guestPolicy, String);
const selector = {
meetingId,
};
const modifier = {
$set: {
'usersProp.guestPolicy': guestPolicy,
},
};
try {
const { numberAffected } = await Meetings.upsertAsync(selector, modifier);
if (numberAffected) {
Logger.verbose(`Set guest policy meetingId=${meetingId} guestPolicy=${guestPolicy}`);
}
} catch (err) {
Logger.error(`Setting guest policy: ${err}`);
}
}

View File

@ -1,28 +0,0 @@
import Meetings from '/imports/api/meetings';
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check';
export default async function setPublishedPoll(meetingId, isPublished) {
check(meetingId, String);
check(isPublished, Boolean);
const selector = {
meetingId,
};
const modifier = {
$set: {
publishedPoll: isPublished,
},
};
try {
const { numberAffected } = await Meetings.upsert(selector, modifier);
if (numberAffected) {
Logger.info(`Set publishedPoll=${isPublished} in meeitingId=${meetingId}`);
}
} catch (err) {
Logger.error(`Setting publishedPoll=${isPublished} for meetingId=${meetingId}`);
}
}

View File

@ -1,29 +0,0 @@
import Logger from '/imports/startup/server/logger';
import { LayoutMeetings } from '/imports/api/meetings';
import { check } from 'meteor/check';
export default async function setPushLayout(meetingId, pushLayout, requesterUserId) {
try {
check(meetingId, String);
check(requesterUserId, String);
const selector = {
meetingId,
};
// TODO: create a exclusive collection for layout changes
const modifier = {
$set: {
pushLayout,
},
};
const numberAffected = await LayoutMeetings.updateAsync(selector, modifier);
if (numberAffected) {
Logger.info(`MeetingLayout pushLayout changed to ${pushLayout} for meeting=${meetingId} requested by user=${requesterUserId}`);
}
} catch (err) {
Logger.error(`Exception while invoking method setPushLayout ${err.stack}`);
}
}

View File

@ -1,34 +0,0 @@
import Logger from '/imports/startup/server/logger';
import Meetings from '/imports/api/meetings';
import { check } from 'meteor/check';
export default async function changeWebcamOnlyModerator(meetingId, payload) {
check(meetingId, String);
check(payload, {
webcamsOnlyForModerator: Boolean,
setBy: String,
});
const { webcamsOnlyForModerator } = payload;
const selector = {
meetingId,
};
const modifier = {
$set: {
'usersProp.webcamsOnlyForModerator': webcamsOnlyForModerator,
},
};
try {
const { numberAffected } = await Meetings.upsertAsync(selector, modifier);
if (numberAffected) {
Logger.info(`Changed meeting={${meetingId}} updated webcam Only for Moderator`);
} else {
Logger.info(`meeting={${meetingId}} webcam Only for Moderator were not updated`);
}
} catch (err) {
Logger.error(`Changwing meeting={${meetingId}} webcam Only for Moderator: ${err}`);
}
}

View File

@ -1,7 +1,6 @@
import '/imports/startup/server';
// 2x
import '/imports/api/meetings/server';
// Commons
import '/imports/api/log-client/server';