diff --git a/bigbluebutton-html5/imports/api/common/server/helpers.js b/bigbluebutton-html5/imports/api/common/server/helpers.js index 72763a4eaabd7307e896da7d43dbb4e69ab6577c..d95ee4b81814e81b47acdee24254394573e4448f 100755 --- a/bigbluebutton-html5/imports/api/common/server/helpers.js +++ b/bigbluebutton-html5/imports/api/common/server/helpers.js @@ -6,7 +6,7 @@ import { clearPresentationsCollection } from '/imports/api/presentations/server/modifiers/clearPresentationsCollection'; import { clearMeetingsCollection } from '/imports/api/meetings/server/modifiers/clearMeetingsCollection'; -import { clearPollCollection } from '/imports/api/polls/server/modifiers/clearPollCollection'; +import clearPolls from '/imports/api/polls/server/modifiers/clearPolls'; import { clearCursorCollection } from '/imports/api/cursor/server/modifiers/clearCursorCollection'; import { clearCaptionsCollection } from '/imports/api/captions/server/modifiers/clearCaptionsCollection'; @@ -44,7 +44,7 @@ export function clearCollections() { clearShapesCollection(meetingId); clearSlidesCollection(meetingId); clearPresentationsCollection(meetingId); - clearPollCollection(meetingId); + clearPolls(meetingId); clearCursorCollection(meetingId); clearCaptionsCollection(meetingId); } else { @@ -54,7 +54,7 @@ export function clearCollections() { clearShapesCollection(); clearSlidesCollection(); clearPresentationsCollection(); - clearPollCollection(); + clearPolls(); clearCursorCollection(); clearCaptionsCollection(); } diff --git a/bigbluebutton-html5/imports/api/polls/index.js b/bigbluebutton-html5/imports/api/polls/index.js old mode 100755 new mode 100644 diff --git a/bigbluebutton-html5/imports/api/polls/server/eventHandlers.js b/bigbluebutton-html5/imports/api/polls/server/eventHandlers.js new file mode 100644 index 0000000000000000000000000000000000000000..5aa523d7979b0308f28fad2ba1edc26744d6a905 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/eventHandlers.js @@ -0,0 +1,9 @@ +import RedisPubSub from '/imports/startup/server/redis'; +import handleShowResult from './handlers/showResult'; +import handlePollStarted from './handlers/pollStarted'; +import handleUserVoted from './handlers/userVoted'; + +RedisPubSub.on('poll_show_result_message', handleShowResult); +RedisPubSub.on('poll_started_message', handlePollStarted); +RedisPubSub.on('poll_stopped_message', handleShowResult); +RedisPubSub.on('user_voted_poll_message', handleUserVoted); diff --git a/bigbluebutton-html5/imports/api/polls/server/handlers/pollStarted.js b/bigbluebutton-html5/imports/api/polls/server/handlers/pollStarted.js new file mode 100644 index 0000000000000000000000000000000000000000..d9ebb195ce07b21599610eb411df7a734bef908c --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/handlers/pollStarted.js @@ -0,0 +1,33 @@ +import Meetings from '/imports/api/meetings'; +import Users from '/imports/api/users'; +import { check } from 'meteor/check'; +import addPoll from '../modifiers/addPoll'; + +export default function pollStarted({ payload }) { + check(payload, Object); + + const meetingId = payload.meeting_id; + const requesterId = payload.requester_id; + const poll = payload.poll; + + check(meetingId, String); + check(requesterId, String); + check(poll, Object); + + const documentExists = Meetings.findOne({ + meetingId: meetingId, + }); + + if (documentExists) { + const users = Users.find({ + meetingId: meetingId, + }, { + fields: { + 'user.userid': 1, + _id: 0, + }, + }).fetch(); + + addPoll(poll, requesterId, users, meetingId); + } +} diff --git a/bigbluebutton-html5/imports/api/polls/server/handlers/showResult.js b/bigbluebutton-html5/imports/api/polls/server/handlers/showResult.js new file mode 100644 index 0000000000000000000000000000000000000000..d748994d1adec9049997de25c0b5e3fd19828561 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/handlers/showResult.js @@ -0,0 +1,15 @@ +import { check } from 'meteor/check'; +import clearPolls from '../modifiers/clearPolls'; + +export default function pollStopped({ payload }) { + check(payload, Object); + + console.log(payload); + const meetingId = payload.meeting_id; + const pollId = payload.poll.id; + + check(meetingId, String); + check(pollId, String); + + clearPolls(meetingId, pollId); +} diff --git a/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js b/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js new file mode 100644 index 0000000000000000000000000000000000000000..b450488eb90a5fa1df8f6aa9c2e5e5018d9edda5 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js @@ -0,0 +1,16 @@ +import { check } from 'meteor/check'; +import updatePoll from '../modifiers/updatePoll'; + +export default function userVoted({ payload }) { + check(payload, Object); + + const meetingId = payload.meeting_id; + const poll = payload.poll; + const requesterId = payload.presenter_id; + + check(meetingId, String); + check(poll, Object); + check(requesterId, String); + + updatePoll(poll, meetingId, requesterId); +}; diff --git a/bigbluebutton-html5/imports/api/polls/server/index.js b/bigbluebutton-html5/imports/api/polls/server/index.js new file mode 100644 index 0000000000000000000000000000000000000000..92451ac76bf27410726e8f3cd2eebac46cd7b83e --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/index.js @@ -0,0 +1,3 @@ +import './eventHandlers'; +import './methods'; +import './publishers'; diff --git a/bigbluebutton-html5/imports/api/polls/server/methods.js b/bigbluebutton-html5/imports/api/polls/server/methods.js new file mode 100644 index 0000000000000000000000000000000000000000..4136d79f73d2d95adb61d39aa729744b17a882f4 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/methods.js @@ -0,0 +1,6 @@ +import { Meteor } from 'meteor/meteor'; +import publishVote from './methods/publishVote'; + +Meteor.methods({ + publishVote, +}); diff --git a/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js b/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js new file mode 100644 index 0000000000000000000000000000000000000000..e295d4e323405fdd973d0fdca4a856004e7b4b16 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js @@ -0,0 +1,47 @@ +import { publish } from '/imports/api/common/server/helpers'; +import { isAllowedTo } from '/imports/startup/server/userPermissions'; +import { appendMessageHeader } from '/imports/api/common/server/helpers'; +import Polls from '/imports/api/polls'; +import { logger } from '/imports/startup/server/logger'; + +export default function publishVote(credentials, pollId, pollAnswerId) { //TODO discuss location + const REDIS_CONFIG = Meteor.settings.redis; + if (isAllowedTo('subscribePoll', credentials)) { + const { meetingId, requesterUserId, requesterToken } = credentials; + const eventName = 'vote_poll_user_request_message'; + + const result = Polls.findOne({ + users: requesterUserId, + meetingId: meetingId, + 'poll.answers.id': pollAnswerId, + 'poll.id': pollId, + }); + + if ((meetingId != null) && + (result.meetingId != null) && + (requesterUserId != null) && + (pollAnswerId != null)) { + let message = { + payload: { + meeting_id: result.meetingId, + user_id: requesterUserId, + poll_id: result.poll.id, + question_id: 0, + answer_id: pollAnswerId, + }, + }; + Polls.update({ + users: requesterUserId, + meetingId: meetingId, + 'poll.answers.id': pollAnswerId, + }, { + $pull: { + users: requesterUserId, + }, + }); + message = appendMessageHeader(eventName, message); + logger.info('publishing Poll response to redis'); + return publish(REDIS_CONFIG.channels.toBBBApps.polling, message); + } + } +} diff --git a/bigbluebutton-html5/imports/api/polls/server/methods/publishVoteMessage.js b/bigbluebutton-html5/imports/api/polls/server/methods/publishVoteMessage.js deleted file mode 100755 index 9e88c0505d51b19cfc068bf130f191eba5381aff..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/polls/server/methods/publishVoteMessage.js +++ /dev/null @@ -1,49 +0,0 @@ -import { publish } from '/imports/api/common/server/helpers'; -import { isAllowedTo } from '/imports/startup/server/userPermissions'; -import { appendMessageHeader } from '/imports/api/common/server/helpers'; -import Polls from '/imports/api/polls'; -import { logger } from '/imports/startup/server/logger'; - -Meteor.methods({ - publishVoteMessage(credentials, pollId, pollAnswerId) { //TODO discuss location - const REDIS_CONFIG = Meteor.settings.redis; - if (isAllowedTo('subscribePoll', credentials)) { - const { meetingId, requesterUserId, requesterToken } = credentials; - const eventName = 'vote_poll_user_request_message'; - - const result = Polls.findOne({ - users: requesterUserId, - meetingId: meetingId, - 'poll.answers.id': pollAnswerId, - 'poll.id': pollId, - }); - - if ((meetingId != null) && - (result.meetingId != null) && - (requesterUserId != null) && - (pollAnswerId != null)) { - let message = { - payload: { - meeting_id: result.meetingId, - user_id: requesterUserId, - poll_id: result.poll.id, - question_id: 0, - answer_id: pollAnswerId, - }, - }; - Polls.update({ - users: requesterUserId, - meetingId: meetingId, - 'poll.answers.id': pollAnswerId, - }, { - $pull: { - users: requesterUserId, - }, - }); - message = appendMessageHeader(eventName, message); - logger.info('publishing Poll response to redis'); - return publish(REDIS_CONFIG.channels.toBBBApps.polling, message); - } - } - }, -}); diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/addPollToCollection.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js old mode 100755 new mode 100644 similarity index 69% rename from bigbluebutton-html5/imports/api/polls/server/modifiers/addPollToCollection.js rename to bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js index 6ac5fb87e1749c476687afd3c26d89038e42b8d9..a24940914bb767c62e981c24d5e80ac12172035e --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/addPollToCollection.js +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js @@ -1,14 +1,14 @@ import Polls from '/imports/api/polls'; import { logger } from '/imports/startup/server/logger'; +import { check } from 'meteor/check'; -export function addPollToCollection(poll, requesterId, users, meetingId) { - // copying all the userids into an array - let newUsers = []; - newUsersLength = users.length; - for (let i = 0; i < newUsersLength; i++) { - const user = users[i]; - newUsers.push(user.user.userid); - } +export default function addPoll(poll, requesterId, users, meetingId) { + check(poll, Object); + check(requesterId, String); + check(users, Array); + check(meetingId, String); + + const userIds = users.map(user => user.user.userid); // adding the initial number of votes for each answer // _answers = poll.answers; @@ -24,14 +24,14 @@ export function addPollToCollection(poll, requesterId, users, meetingId) { numRespondents = -1; // adding all together and inserting into the Polls collection - const entry = { + const newPoll = { meetingId: meetingId, poll: poll, requester: requesterId, - users: newUsers, + users: userIds, num_responders: -1, num_respondents: -1, }; logger.info(`added poll _id=[${poll.id}]:meetingId=[${meetingId}].`); - return Polls.insert(entry); + return Polls.insert(newPoll); }; diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPollCollection.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js old mode 100755 new mode 100644 similarity index 71% rename from bigbluebutton-html5/imports/api/polls/server/modifiers/clearPollCollection.js rename to bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js index 5070cb700f616c9bc14b3f1475cf6b00cfe7a044..982f245ef9985383966c15e24942bf022e0e62c8 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPollCollection.js +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js @@ -1,12 +1,13 @@ import Polls from '/imports/api/polls'; +import { check } from 'meteor/check'; import { logger } from '/imports/startup/server/logger'; -export function clearPollCollection() { - const meetingId = arguments[0]; - const pollId = arguments[1]; - +export default function clearPolls(meetingId, pollId) { //TODO make it so you can delete the polls based only on meetingId - if (meetingId != null && pollId != null) { + check(meetingId, String); + check(pollId, String); + + if (meetingId && pollId) { return Polls.remove({ meetingId: meetingId, 'poll.id': pollId, diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/eventHandlers.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/eventHandlers.js deleted file mode 100644 index 20bbc4c92ca13b4e8fd9997c2b5b20ac2fcd12bb..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/eventHandlers.js +++ /dev/null @@ -1,70 +0,0 @@ -import { eventEmitter } from '/imports/startup/server'; -import { clearPollCollection } from './clearPollCollection'; -import { updatePollCollection } from './updatePollCollection'; -import { addPollToCollection } from './addPollToCollection'; -import Meetings from '/imports/api/meetings'; -import Users from '/imports/api/users'; - -eventEmitter.on('poll_show_result_message', function (arg) { - const payload = arg.payload; - const meetingId = payload.meeting_id; - if (payload != null && payload.poll != null && payload.poll.id != null && meetingId != null) { - const pollId = payload.poll.id; - clearPollCollection(meetingId, pollId); - } - - return arg.callback(); -}); - -eventEmitter.on('poll_started_message', function (arg) { - const payload = arg.payload; - const meetingId = payload.meeting_id; - - if (payload != null && meetingId != null && - payload.requester_id != null && payload.poll != null) { - if (Meetings.findOne({ - meetingId: meetingId, - }) != null) { - const users = Users.find({ - meetingId: meetingId, - }, { - fields: { - 'user.userid': 1, - _id: 0, - }, - }).fetch(); - addPollToCollection( - payload.poll, - payload.requester_id, - users, - meetingId - ); - } - } - - return arg.callback(); -}); - -eventEmitter.on('poll_stopped_message', function (arg) { - const payload = arg.payload; - const meetingId = payload.meeting_id; - - if (meetingId != null && payload != null && payload.poll_id != null) { - const pollId = payload.poll_id; - clearPollCollection(meetingId, pollId); - } - - return arg.callback(); -}); - -eventEmitter.on('user_voted_poll_message', function (arg) { - const payload = arg.payload; - const meetingId = payload.meeting_id; - if (payload != null && payload.poll != null && meetingId != null && - payload.presenter_id != null) { - const pollObj = payload.poll; - const requesterId = payload.presenter_id; - updatePollCollection(pollObj, meetingId, requesterId); - return arg.callback(); - } -}); diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/updatePoll.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/updatePoll.js new file mode 100644 index 0000000000000000000000000000000000000000..a7efbe365b7359e306039f885f830298622809d0 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/updatePoll.js @@ -0,0 +1,35 @@ +import Polls from '/imports/api/polls'; +import { check } from 'meteor/check'; +import { logger } from '/imports/startup/server/logger'; + +export default function updatePoll(poll, meetingId, requesterId) { + check(meetingId, String); + check(requesterId, String); + check(poll, Object); + + const { + id, + answers, + } = poll; + + const numResponders = poll.num_responders; + const numRespondents = poll.num_respondents; + + check(id, String); + check(answers, Array); + + check(numResponders, Number); + check(numRespondents, Number); + + return Polls.update({ + meetingId: meetingId, + requester: requesterId, + poll: { id: id }, + }, { + $set: { + poll: { answers: answers }, + poll: { num_responders: numResponders }, + poll: { num_respondents: numRespondents }, + }, + }, logger.info(`updating Polls Collection (meetingId: ${meetingId}, pollId: ${id}!)`)); +}; diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/updatePollCollection.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/updatePollCollection.js deleted file mode 100755 index e224c5932f9a99d645c42fa441ade80459e9e183..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/updatePollCollection.js +++ /dev/null @@ -1,19 +0,0 @@ -import Polls from '/imports/api/polls'; -import { logger } from '/imports/startup/server/logger'; - -export function updatePollCollection(poll, meetingId, requesterId) { - if ((poll.answers != null) && (poll.numResponders != null) && (poll.numRespondents != null) && - (poll.id != null) && (meetingId != null) && (requesterId != null)) { - return Polls.update({ - meetingId: meetingId, - requester: requesterId, - poll: { id: poll.id }, - }, { - $set: { - poll: { answers: poll.answers }, - poll: { num_responders: poll.numResponders }, - poll: { num_respondents: poll.numRespondents }, - }, - }, logger.info(`updating Polls Collection (meetingId: ${meetingId}, pollId: ${poll.id}!)`)); - } -}; diff --git a/bigbluebutton-html5/imports/api/polls/server/publications.js b/bigbluebutton-html5/imports/api/polls/server/publications.js deleted file mode 100755 index 7092ebe1beca24c6f2eaaaf468609ec6ae15f5c8..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/polls/server/publications.js +++ /dev/null @@ -1,33 +0,0 @@ -import { isAllowedTo } from '/imports/startup/server/userPermissions'; -import Polls from '/imports/api/polls'; -import { logger } from '/imports/startup/server/logger'; - -Meteor.publish('polls', function (credentials) { - const { meetingId, requesterUserId, requesterToken } = credentials; - - //checking if it is allowed to see Poll Collection in general - if (isAllowedTo('subscribePoll', credentials)) { - //checking if it is allowed to see a number of votes (presenter only) - if (isAllowedTo('subscribeAnswers', credentials)) { - logger.info('publishing Poll for presenter: ' + meetingId + ' ' + requesterUserId + ' ' + - requesterToken); - return Polls.find({ - meetingId: meetingId, - users: requesterUserId, - }); - } else { - logger.info('publishing Poll for viewer: ' + meetingId + ' ' + requesterUserId + ' ' + - requesterToken); - return Polls.find({ - meetingId: meetingId, - users: requesterUserId, - }, { - fields: { - 'poll.answers.num_votes': 0, - }, - }); - } - } else { - this.error(new Meteor.Error(402, "The user was not authorized to subscribe for 'polls'")); - } -}); diff --git a/bigbluebutton-html5/imports/api/polls/server/publishers.js b/bigbluebutton-html5/imports/api/polls/server/publishers.js new file mode 100644 index 0000000000000000000000000000000000000000..23c1593b503a9c294648e0c1167592ca01ac5151 --- /dev/null +++ b/bigbluebutton-html5/imports/api/polls/server/publishers.js @@ -0,0 +1,37 @@ +import { Meteor } from 'meteor/meteor'; +import { isAllowedTo } from '/imports/startup/server/userPermissions'; +import Polls from '/imports/api/polls'; +import { check } from 'meteor/check'; +import { logger } from '/imports/startup/server/logger'; + +Meteor.publish('polls', (credentials) => { + //checking if it is allowed to see Poll Collection in general + if (!isAllowedTo('subscribePoll', credentials)) { + this.error(new Meteor.Error(402, "The user was not authorized to subscribe for 'polls'")); + } + + const { meetingId, requesterUserId, requesterToken } = credentials; + + check(meetingId, String); + check(requesterUserId, String); + check(requesterToken, String); + + //checking if it is allowed to see a number of votes (presenter only) + if (isAllowedTo('subscribeAnswers', credentials)) { + logger.info(`publishing Poll for presenter: ${meetingId} ${requesterUserId} ${requesterToken}`); + return Polls.find({ + meetingId: meetingId, + users: requesterUserId, + }); + } else { + logger.info(`publishing Poll for viewer: ${meetingId} ${requesterUserId} ${requesterToken}`); + return Polls.find({ + meetingId: meetingId, + users: requesterUserId, + }, { + fields: { + 'poll.answers.num_votes': 0, + }, + }); + } +}); diff --git a/bigbluebutton-html5/imports/ui/components/polling/service.js b/bigbluebutton-html5/imports/ui/components/polling/service.js index 6741436dd6d4a199a28340e4f9787dad51645b8f..a2fc2746f2ac81b5a8b46a3cbfc3b6f461c056b8 100755 --- a/bigbluebutton-html5/imports/ui/components/polling/service.js +++ b/bigbluebutton-html5/imports/ui/components/polling/service.js @@ -17,7 +17,7 @@ let mapPolls = function () { pollExists: true, amIRequester: amIRequester, handleVote: function (pollId, answerId) { - callServer('publishVoteMessage', pollId, answerId.id); + callServer('publishVote', pollId, answerId.id); }, }; }; diff --git a/bigbluebutton-html5/server/main.js b/bigbluebutton-html5/server/main.js index eb20f0fd160a23953928d248529d77c8c08dacc6..9374f2ae63e041e297b8fd72d3cc6820b83977c1 100755 --- a/bigbluebutton-html5/server/main.js +++ b/bigbluebutton-html5/server/main.js @@ -21,12 +21,7 @@ import '/imports/api/meetings/server/modifiers/eventHandlers'; import '/imports/api/phone/server/modifiers/eventHandlers'; -import '/imports/api/polls/server/publications'; -import '/imports/api/polls/server/methods/publishVoteMessage'; -import '/imports/api/polls/server/modifiers/addPollToCollection'; -import '/imports/api/polls/server/modifiers/clearPollCollection'; -import '/imports/api/polls/server/modifiers/updatePollCollection'; -import '/imports/api/polls/server/modifiers/eventHandlers'; +import '/imports/api/polls/server'; import '/imports/api/presentations/server/publications'; import '/imports/api/presentations/server/methods/switchSlideMessage';