1
1
'use strict' ;
2
2
3
+ const _ = require . main . require ( 'lodash' ) ;
3
4
const NodeBB = require ( './nodebb' ) ;
4
5
5
6
const Config = require ( './config' ) ;
@@ -31,6 +32,10 @@ Sockets.get = async function (socket, data) {
31
32
throw new Error ( 'Legacy polls are not supported' ) ;
32
33
}
33
34
35
+ if ( parseInt ( pollData . settings . allowAnonVoting , 10 ) === 1 ) {
36
+ await anonymizeVoters ( socket . uid , data . pollId , pollData . options ) ;
37
+ }
38
+
34
39
pollData . optionType = parseInt ( pollData . settings . maxvotes , 10 ) > 1 ? 'checkbox' : 'radio' ;
35
40
return pollData ;
36
41
} ;
@@ -59,6 +64,10 @@ Sockets.vote = async function (socket, data) {
59
64
throw new Error ( `You can only vote for ${ settings . maxvotes } options on this poll.` ) ;
60
65
}
61
66
67
+ if ( data . voteAnon && parseInt ( settings . allowAnonVoting , 10 ) !== 1 ) {
68
+ throw new Error ( '[[poll:error.anon-voting-not-allowed]]' ) ;
69
+ }
70
+
62
71
if ( ! canVote || ! data . options . length ) {
63
72
throw new Error ( 'Already voted or invalid option' ) ;
64
73
}
@@ -128,14 +137,20 @@ Sockets.getOptionDetails = async function (socket, data) {
128
137
if ( ! socket . uid || ! data || isNaN ( parseInt ( data . pollId , 10 ) ) || isNaN ( parseInt ( data . optionId , 10 ) ) ) {
129
138
throw new Error ( 'Invalid request' ) ;
130
139
}
131
- const [ poll , option ] = await Promise . all ( [
140
+ const [ poll , settings , option ] = await Promise . all ( [
132
141
Poll . getInfo ( data . pollId ) ,
142
+ Poll . getSettings ( data . pollId ) ,
133
143
Poll . getOption ( data . pollId , data . optionId , true ) ,
134
144
] ) ;
135
145
136
146
if ( ! option . votes || ! option . votes . length ) {
137
147
return option ;
138
148
}
149
+
150
+ if ( parseInt ( settings . allowAnonVoting , 10 ) === 1 ) {
151
+ await anonymizeVoters ( socket . uid , data . pollId , [ option ] ) ;
152
+ }
153
+
139
154
const userData = await NodeBB . User . getUsersFields ( option . votes , [
140
155
'uid' , 'username' , 'userslug' , 'picture' ,
141
156
] ) ;
@@ -160,6 +175,23 @@ Sockets.canCreate = async function (socket, data) {
160
175
return await checkPrivs ( data . cid , socket . uid ) ;
161
176
} ;
162
177
178
+ async function anonymizeVoters ( callerUid , pollId , options ) {
179
+ const uids = _ . uniq ( options . map ( opt => opt . votes ) . flat ( ) ) ;
180
+ const [ isAnon , isPrivileged ] = await Promise . all ( [
181
+ NodeBB . db . isSortedSetMembers ( `poll:${ pollId } :anon:voters` , uids ) ,
182
+ NodeBB . User . isPrivileged ( callerUid ) ,
183
+ ] ) ;
184
+ if ( isPrivileged ) {
185
+ return ;
186
+ }
187
+ const uidToIsAnon = _ . zipObject ( uids , isAnon ) ;
188
+ options . forEach ( ( opt ) => {
189
+ opt . votes = opt . votes . map (
190
+ uid => ( uidToIsAnon [ uid ] && String ( callerUid ) !== uid ? 0 : uid )
191
+ ) ;
192
+ } ) ;
193
+ }
194
+
163
195
async function checkPrivs ( cid , socketUid ) {
164
196
const can = await NodeBB . Privileges . categories . can ( 'poll:create' , cid , socketUid ) ;
165
197
if ( ! can ) {
0 commit comments