Skip to content

Commit

Permalink
Add check for min/max of votes totals. (#537)
Browse files Browse the repository at this point in the history
* Add check for min/max of votes totals.

* Update vote.

Remove surplus line.
Remove global total check, should always be one.
Update total test.

* Add min case total test to poll vote.
  • Loading branch information
reiterl committed Mar 18, 2021
1 parent 00635ed commit acef4bb
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 4 deletions.
20 changes: 16 additions & 4 deletions openslides_backend/action/actions/poll/vote.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def fetch_poll(self, poll_id: int) -> Dict[str, Any]:
"entitled_group_ids",
"state",
"votesvalid",
"min_votes_amount",
"max_votes_amount",
],
)

Expand Down Expand Up @@ -125,11 +127,11 @@ def validate_option_value(self, value: Dict[str, Any]) -> None:
def validate_global_value(self, value: str) -> None:
if value not in ("Y", "N", "A"):
raise ActionException(f"Option value {value} is not in 'YNA'.")
if value == "Y" and not self.poll.get("global_yes"):
elif value == "Y" and not self.poll.get("global_yes"):
raise ActionException("Global value Y not allowed.")
if value == "N" and not self.poll.get("global_no"):
elif value == "N" and not self.poll.get("global_no"):
raise ActionException("Global value N not allowed.")
if value == "A" and not self.poll.get("global_abstain"):
elif value == "A" and not self.poll.get("global_abstain"):
raise ActionException("Global value A not allowed.")

def handle_option_value(
Expand All @@ -139,9 +141,12 @@ def handle_option_value(
self._handle_value_keys(value, user_id, action_data)
if action_data:
self.execute_other_action(VoteCreate, action_data)
total_votes = 0
for data in action_data:
self.update_option(data["option_id"], data["value"], data["weight"])
self.update_votes_valid(instance, data["weight"])
total_votes += 1
self.check_total_votes(total_votes)

def _handle_value_keys(
self,
Expand Down Expand Up @@ -269,7 +274,6 @@ def _get_vote_create_action_data(
meeting_id: int,
weight: str,
) -> Dict[str, Any]:
user_id = user_id
if self.poll.get("type") == Poll.TYPE_PSEUDOANONYMOUS:
user_id = None
return {
Expand All @@ -279,3 +283,11 @@ def _get_vote_create_action_data(
"option_id": option_id,
"meeting_id": meeting_id,
}

def check_total_votes(self, total: int) -> None:
if not (
self.poll.get("min_votes_amount", 1)
<= total
<= self.poll.get("max_votes_amount", 1)
):
raise ActionException("Total amount of votes is not in min-max-interval.")
100 changes: 100 additions & 0 deletions tests/system/action/poll/test_vote.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def test_vote_correct_pollmethod_Y(self) -> None:
"meeting_id": 113,
"entitled_group_ids": [1],
"state": Poll.STATE_STARTED,
"min_votes_amount": 1,
"max_votes_amount": 10,
},
"meeting/113": {"name": "my meeting"},
}
Expand Down Expand Up @@ -123,6 +125,8 @@ def test_vote_correct_pollmethod_YN(self) -> None:
"meeting_id": 113,
"entitled_group_ids": [1],
"state": Poll.STATE_STARTED,
"min_votes_amount": 1,
"max_votes_amount": 10,
},
"meeting/113": {"name": "my meeting"},
"user/1": {
Expand Down Expand Up @@ -167,6 +171,88 @@ def test_vote_correct_pollmethod_YN(self) -> None:
assert user.get("vote_$_ids") == ["113", "113"]
assert user.get("vote_$113_ids") == [1, 2]

def test_vote_wrong_votes_total(self) -> None:
self.set_models(
{
"organisation/1": {"enable_electronic_voting": True},
"group/1": {"user_ids": [1]},
"option/11": {"meeting_id": 113, "poll_id": 1},
"option/12": {"meeting_id": 113, "poll_id": 1},
"option/13": {"meeting_id": 113, "poll_id": 1},
"poll/1": {
"title": "my test poll",
"option_ids": [11, 12, 13],
"pollmethod": "YN",
"meeting_id": 113,
"entitled_group_ids": [1],
"state": Poll.STATE_STARTED,
"min_votes_amount": 1,
"max_votes_amount": 1,
},
"meeting/113": {"name": "my meeting"},
"user/1": {
"is_present_in_meeting_ids": [113],
"group_$113_ids": [1],
"group_$_ids": ["113"],
},
}
)
response = self.request(
"poll.vote",
{
"id": 1,
"user_id": 1,
"value": {"11": "Y", "12": "N"},
},
)
self.assert_status_code(response, 400)
assert (
"Total amount of votes is not in min-max-interval."
in response.data.decode()
)
self.assert_model_not_exists("vote/1")

def test_vote_wrong_votes_total_min_case(self) -> None:
self.set_models(
{
"organisation/1": {"enable_electronic_voting": True},
"group/1": {"user_ids": [1]},
"option/11": {"meeting_id": 113, "poll_id": 1},
"option/12": {"meeting_id": 113, "poll_id": 1},
"option/13": {"meeting_id": 113, "poll_id": 1},
"poll/1": {
"title": "my test poll",
"option_ids": [11, 12, 13],
"pollmethod": "YN",
"meeting_id": 113,
"entitled_group_ids": [1],
"state": Poll.STATE_STARTED,
"min_votes_amount": 2,
"max_votes_amount": 2,
},
"meeting/113": {"name": "my meeting"},
"user/1": {
"is_present_in_meeting_ids": [113],
"group_$113_ids": [1],
"group_$_ids": ["113"],
},
}
)
response = self.request(
"poll.vote",
{
"id": 1,
"user_id": 1,
"value": {"11": "Y"},
},
)
self.assert_status_code(response, 400)
assert (
"Total amount of votes is not in min-max-interval."
in response.data.decode()
)
self.assert_model_not_exists("vote/1")

def test_vote_global(self) -> None:
self.set_models(
{
Expand Down Expand Up @@ -534,6 +620,8 @@ def create_poll(self) -> None:
"meeting_id": 113,
"option_ids": [1, 2],
"entitled_group_ids": [1],
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down Expand Up @@ -570,6 +658,8 @@ def create_poll(self) -> None:
"votescast": "0.000000",
"votesvalid": "0.000000",
"votesinvalid": "0.000000",
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down Expand Up @@ -761,6 +851,8 @@ def create_poll(self) -> None:
"global_yes": True,
"global_no": True,
"global_abstain": True,
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down Expand Up @@ -983,6 +1075,8 @@ def create_poll(self) -> None:
"global_yes": True,
"global_no": True,
"global_abstain": True,
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down Expand Up @@ -1194,6 +1288,8 @@ def create_poll(self) -> None:
"option_ids": [1, 2],
"entitled_group_ids": [1],
"votesinvalid": "0.000000",
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down Expand Up @@ -1362,6 +1458,8 @@ def create_poll(self) -> None:
"option_ids": [1, 2],
"entitled_group_ids": [1],
"votesinvalid": "0.000000",
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down Expand Up @@ -1507,6 +1605,8 @@ def create_poll(self) -> None:
"option_ids": [1, 2],
"entitled_group_ids": [1],
"votesinvalid": "0.000000",
"min_votes_amount": 1,
"max_votes_amount": 10,
},
)

Expand Down

0 comments on commit acef4bb

Please sign in to comment.