From d2cb02b3bd670265c6b1ba003f87fc261e0ac3e1 Mon Sep 17 00:00:00 2001
From: KDSBrowne <kert.browne85@gmail.com>
Date: Wed, 28 Oct 2020 18:33:09 +0000
Subject: [PATCH] prevent users from being able to send more than 1 poll vote

---
 .../org/bigbluebutton/core/models/Polls.scala   | 10 +++++++++-
 .../api/polls/server/methods/publishVote.js     | 17 +++++++++++++----
 .../imports/ui/components/polling/service.js    |  9 ++++++---
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Polls.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Polls.scala
index 4aab4ac88c..2d34a5e401 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Polls.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Polls.scala
@@ -313,7 +313,10 @@ object Polls {
   def respondToQuestion(pollId: String, questionID: Int, responseID: Int, responder: Responder, polls: Polls) {
     polls.polls.get(pollId) match {
       case Some(p) => {
-        p.respondToQuestion(questionID, responseID, responder)
+        if (!p._responders.exists(_ == responder)) {
+          p.addResponder(responder)
+          p.respondToQuestion(questionID, responseID, responder)
+        }
       }
       case None =>
     }
@@ -455,6 +458,11 @@ class Poll(val id: String, val questions: Array[Question], val numRespondents: I
   private var _stopped: Boolean = false
   private var _showResult: Boolean = false
   private var _numResponders: Int = 0
+  var _responders = new ArrayBuffer[Responder]()
+
+  def addResponder(responder: Responder) {
+    _responders += (responder)
+  }
 
   def showingResult() { _showResult = true }
   def showResult(): Boolean = { _showResult }
diff --git a/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js b/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js
index 6d5281e43e..a7eba4a3a6 100644
--- a/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js
+++ b/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js
@@ -8,12 +8,21 @@ export default function publishVote(pollId, pollAnswerId) {
   const REDIS_CONFIG = Meteor.settings.private.redis;
   const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
   const EVENT_NAME = 'RespondToPollReqMsg';
-
   const { meetingId, requesterUserId } = extractCredentials(this.userId);
 
   check(pollAnswerId, Number);
   check(pollId, String);
 
+  const waitingFor = Polls.findOne({ id: pollId }, {
+    feilds: {
+      users: 1,
+    },
+  });
+
+  const userResponded = !waitingFor.users.includes(requesterUserId);
+
+  if (userResponded) return null;
+
   const selector = {
     users: requesterUserId,
     meetingId,
@@ -43,11 +52,11 @@ export default function publishVote(pollId, pollAnswerId) {
       return Logger.error(`Removing responded user from Polls collection: ${err}`);
     }
 
-    return Logger.info(`Removed responded user=${requesterUserId} from poll (meetingId: ${meetingId}, `
+    Logger.info(`Removed responded user=${requesterUserId} from poll (meetingId: ${meetingId}, `
       + `pollId: ${pollId}!)`);
+
+    return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
   };
 
   Polls.update(selector, modifier, cb);
-
-  return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
 }
diff --git a/bigbluebutton-html5/imports/ui/components/polling/service.js b/bigbluebutton-html5/imports/ui/components/polling/service.js
index 40c241ec09..e5ecaa8b81 100644
--- a/bigbluebutton-html5/imports/ui/components/polling/service.js
+++ b/bigbluebutton-html5/imports/ui/components/polling/service.js
@@ -1,8 +1,13 @@
 import { makeCall } from '/imports/ui/services/api';
 import Polls from '/imports/api/polls';
+import { debounce } from 'lodash';
 
 const MAX_CHAR_LENGTH = 5;
 
+const handleVote = (pollId, answerId) => {
+  makeCall('publishVote', pollId, answerId.id);
+};
+
 const mapPolls = () => {
   const poll = Polls.findOne({});
   if (!poll) {
@@ -30,9 +35,7 @@ const mapPolls = () => {
     },
     pollExists: true,
     amIRequester,
-    handleVote(pollId, answerId) {
-      makeCall('publishVote', pollId, answerId.id);
-    },
+    handleVote: debounce(handleVote, 500, { leading: true, trailing: false }),
   };
 };
 
-- 
GitLab