diff --git a/bigbluebutton-html5/imports/api/users/server/methods.js b/bigbluebutton-html5/imports/api/users/server/methods.js index bf7007de1e..5e70dbd470 100644 --- a/bigbluebutton-html5/imports/api/users/server/methods.js +++ b/bigbluebutton-html5/imports/api/users/server/methods.js @@ -6,6 +6,7 @@ import changeRole from './methods/changeRole'; import removeUser from './methods/removeUser'; import toggleUserLock from './methods/toggleUserLock'; import userActivitySign from './methods/userActivitySign'; +import userLeftMeeting from './methods/userLeftMeeting'; Meteor.methods({ setEmojiStatus, @@ -15,4 +16,5 @@ Meteor.methods({ validateAuthToken, toggleUserLock, userActivitySign, + userLeftMeeting, }); diff --git a/bigbluebutton-html5/imports/api/users/server/methods/userLeftMeeting.js b/bigbluebutton-html5/imports/api/users/server/methods/userLeftMeeting.js new file mode 100644 index 0000000000..4723ba94e5 --- /dev/null +++ b/bigbluebutton-html5/imports/api/users/server/methods/userLeftMeeting.js @@ -0,0 +1,39 @@ +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; +import Logger from '/imports/startup/server/logger'; +import Users from '/imports/api/users'; + +export default function userLeftMeeting(credentials) { + const { + meetingId, + requesterUserId, + } = credentials; + + check(meetingId, String); + check(requesterUserId, String); + + const selector = { + meetingId, + userId: requesterUserId, + }; + + const cb = (err, numChanged) => { + if (err) { + Logger.error(`leaving dummy user to collection: ${err}`); + return; + } + if (numChanged) { + Logger.info(`user left id=${requesterUserId} meeting=${meetingId}`); + } + }; + + return Users.update( + selector, + { + $set: { + loggedOut: true, + }, + }, + cb, + ); +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js index cc5781dbd9..d10c706ace 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js @@ -82,6 +82,7 @@ export default function addUser(meetingId, user) { }, inactivityCheck: false, responseDelay: 0, + loggedOut: false, }, flat(user), ), diff --git a/bigbluebutton-html5/imports/startup/client/base.jsx b/bigbluebutton-html5/imports/startup/client/base.jsx index 24912538b2..bc90953982 100755 --- a/bigbluebutton-html5/imports/startup/client/base.jsx +++ b/bigbluebutton-html5/imports/startup/client/base.jsx @@ -161,6 +161,7 @@ class Base extends Component { meetingHasEnded, meetingIsBreakout, subscriptionsReady, + User, } = this.props; if ((loading || !subscriptionsReady) && !meetingHasEnded && meetingExist) { @@ -175,7 +176,7 @@ class Base extends Component { if (meetingHasEnded && meetingIsBreakout) window.close(); - if (meetingHasEnded && !meetingIsBreakout) { + if (((meetingHasEnded && !meetingIsBreakout)) || (codeError && (User && User.loggedOut))) { AudioManager.exitAudio(); return (); } @@ -216,6 +217,7 @@ const BaseContainer = withTracker(() => { let breakoutRoomSubscriptionHandler; let meetingModeratorSubscriptionHandler; + const User = Users.findOne({ intId: credentials.requesterUserId }); const meeting = Meetings.findOne({ meetingId }); if (meeting) { const { meetingEnded } = meeting; @@ -226,6 +228,7 @@ const BaseContainer = withTracker(() => { const ejected = Users.findOne({ userId: Auth.userID, ejected: true }); if (Session.get('codeError')) { return { + User, meetingHasEnded: !!meeting && meeting.meetingEnded, approved, ejected, @@ -235,7 +238,6 @@ const BaseContainer = withTracker(() => { let userSubscriptionHandler; - const User = Users.findOne({ intId: credentials.requesterUserId }); Breakouts.find().observeChanges({ added() { diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx index bf79a4e706..bbf74258ad 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx @@ -4,7 +4,7 @@ import _ from 'lodash'; import PropTypes from 'prop-types'; import { withModalMounter } from '/imports/ui/components/modal/service'; import EndMeetingConfirmationContainer from '/imports/ui/components/end-meeting-confirmation/container'; -import MeetingEndedComponent from '/imports/ui/components/meeting-ended/component'; +import { makeCall } from '/imports/ui/services/api'; import AboutContainer from '/imports/ui/components/about/container'; import SettingsMenuContainer from '/imports/ui/components/settings/container'; import Button from '/imports/ui/components/button/component'; @@ -110,6 +110,15 @@ const defaultProps = { }; class SettingsDropdown extends PureComponent { + static leaveSession() { + document.dispatchEvent(new Event('exitVideo')); + const LOGOUT_CODE = '403'; + makeCall('userLeftMeeting'); + // we don't check askForFeedbackOnLogout here, + // it is checked in meeting-ended component + Session.set('codeError', LOGOUT_CODE); + // mountModal(); + } constructor(props) { super(props); @@ -164,15 +173,6 @@ class SettingsDropdown extends PureComponent { ); } - leaveSession() { - document.dispatchEvent(new Event('exitVideo')); - const { mountModal } = this.props; - const LOGOUT_CODE = '430'; - // we don't check askForFeedbackOnLogout here, - // it is checked in meeting-ended component - mountModal(); - } - renderMenuItems() { const { intl, mountModal, amIModerator, isBreakoutRoom,