1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 16:22:43 +01:00

Prevent users from voting for invalid Slowvote options

Summary:
Depends on D19773. See <https://hackerone.com/reports/434116>. You can currently vote for invalid options by submitting, e.g., `vote[]=12345`.

By doing this, you can see the responses, which is sort of theoretically a security problem? This is definitely a bug, regardless.

Instead, only allow users to vote for options which are actually part of the poll.

Test Plan:
  - Tried to vote for invalid options by editing the form to `vote[]=12345` (got error).
  - Tried to vote for invalid options by editing the radio buttons on a plurality poll into checkboxes, checking multiple boxes, and submitting (got error).
  - Voted in approval and plurality polls the right way, from the main web UI and from the embed (`{V...}`) UI.

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D19774
This commit is contained in:
epriestley 2018-11-05 10:19:50 -08:00
parent 5e1d94f336
commit d38e768ed8

View file

@ -7,6 +7,10 @@ final class PhabricatorSlowvoteVoteController
$viewer = $request->getViewer(); $viewer = $request->getViewer();
$id = $request->getURIData('id'); $id = $request->getURIData('id');
if (!$request->isFormPost()) {
return id(new Aphront404Response());
}
$poll = id(new PhabricatorSlowvoteQuery()) $poll = id(new PhabricatorSlowvoteQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($id)) ->withIDs(array($id))
@ -16,31 +20,36 @@ final class PhabricatorSlowvoteVoteController
if (!$poll) { if (!$poll) {
return new Aphront404Response(); return new Aphront404Response();
} }
if ($poll->getIsClosed()) { if ($poll->getIsClosed()) {
return new Aphront400Response(); return new Aphront400Response();
} }
$options = $poll->getOptions(); $options = $poll->getOptions();
$viewer_choices = $poll->getViewerChoices($viewer); $options = mpull($options, null, 'getID');
$old_votes = mpull($viewer_choices, null, 'getOptionID'); $old_votes = $poll->getViewerChoices($viewer);
$old_votes = mpull($old_votes, null, 'getOptionID');
if (!$request->isFormPost()) {
return id(new Aphront404Response());
}
$votes = $request->getArr('vote'); $votes = $request->getArr('vote');
$votes = array_fuse($votes); $votes = array_fuse($votes);
$this->updateVotes($viewer, $poll, $old_votes, $votes); $method = $poll->getMethod();
$is_plurality = ($method == PhabricatorSlowvotePoll::METHOD_PLURALITY);
return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID()); if ($is_plurality && count($votes) > 1) {
} throw new Exception(
pht('In this poll, you may only vote for one option.'));
}
private function updateVotes($viewer, $poll, $old_votes, $votes) { foreach ($votes as $vote) {
if (!empty($votes) && count($votes) > 1 && if (!isset($options[$vote])) {
$poll->getMethod() == PhabricatorSlowvotePoll::METHOD_PLURALITY) { throw new Exception(
return id(new Aphront400Response()); pht(
'Option ("%s") is not a valid poll option. You may only '.
'vote for valid options.',
$vote));
}
} }
foreach ($old_votes as $old_vote) { foreach ($old_votes as $old_vote) {
@ -60,6 +69,9 @@ final class PhabricatorSlowvoteVoteController
->setOptionID($vote) ->setOptionID($vote)
->save(); ->save();
} }
return id(new AphrontRedirectResponse())
->setURI($poll->getURI());
} }
} }