From 3f714bb91e543cd2f79f38a4b75e2bf93aaa1b5b Mon Sep 17 00:00:00 2001 From: dartcafe Date: Sat, 28 Dec 2024 11:28:31 +0100 Subject: [PATCH 1/2] fix vote limit check Signed-off-by: dartcafe --- lib/Service/VoteService.php | 42 +++++++++++++++++++----- src/js/components/VoteTable/VoteItem.vue | 4 +++ src/js/store/modules/votes.js | 1 + 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/Service/VoteService.php b/lib/Service/VoteService.php index 3b04389ab..32acd4c21 100644 --- a/lib/Service/VoteService.php +++ b/lib/Service/VoteService.php @@ -15,12 +15,14 @@ use OCA\Polls\Db\Vote; use OCA\Polls\Db\VoteMapper; use OCA\Polls\Event\VoteSetEvent; +use OCA\Polls\Exceptions\NotFoundException; use OCA\Polls\Exceptions\VoteLimitExceededException; use OCA\Polls\Model\Acl as Acl; use OCP\AppFramework\Db\DoesNotExistException; use OCP\EventDispatcher\IEventDispatcher; -class VoteService { +class VoteService +{ /** * @psalm-suppress PossiblyUnusedMethod */ @@ -31,18 +33,18 @@ public function __construct( private PollMapper $pollMapper, private Vote $vote, private VoteMapper $voteMapper, - ) { - } + ) {} /** * Read all votes of a poll based on the poll id and return list as array * * @return Vote[] */ - public function list(int $pollId): array { + public function list(int $pollId): array + { $poll = $this->pollMapper->find($pollId); $poll->request(Poll::PERMISSION_POLL_VIEW); - + if (!$poll->getIsAllowed(Poll::PERMISSION_POLL_RESULTS_VIEW)) { // Just return the participants votes, no further anoymizing or obfuscating is nessecary return $this->voteMapper->findByPollAndUser($pollId, ($this->acl->getCurrentUserId())); @@ -53,7 +55,8 @@ public function list(int $pollId): array { return $votes; } - private function checkLimits(Option $option): void { + private function checkLimits(Option $option): void + { // check, if the optionlimit is reached or exceeded, if one is set if ($option->getIsLockedByOptionLimit()) { throw new VoteLimitExceededException; @@ -65,14 +68,33 @@ private function checkLimits(Option $option): void { return; } + private function checkVoteLimit(Option $option): void + { + // check, if the optionlimit is reached or exceeded, if one is set + if ($option->getIsLockedByOptionLimit()) { + throw new VoteLimitExceededException(); + } + + if ($option->getIsLockedByVotesLimit()) { + throw new VoteLimitExceededException; + } + return; + } + /** * Set vote */ - public function set(int $optionId, string $setTo): ?Vote { + public function set(int $optionId, string $setTo): ?Vote + { $option = $this->optionMapper->find($optionId); $poll = $this->pollMapper->find($option->getPollId()); $poll->request(Poll::PERMISSION_VOTE_EDIT); + if ($option->getIsLocked()) { + $this->checkVoteLimit($option); + throw new NotFoundException(); + } + try { $this->vote = $this->voteMapper->findSingleVote($poll->getId(), $option->getPollOptionText(), $this->acl->getCurrentUserId()); @@ -117,7 +139,8 @@ public function set(int $optionId, string $setTo): ?Vote { * @param string $userId user id of the user, the votes get deleted from * @param bool $deleteOnlyOrphaned - false deletes all votes of the specified user, true only the orphaned votes aka votes without an option */ - public function deleteUserFromPoll(int $pollId, string $userId = '', bool $deleteOnlyOrphaned = false): string { + public function deleteUserFromPoll(int $pollId, string $userId = '', bool $deleteOnlyOrphaned = false): string + { if ($userId === '') { // if no user set, use current user $userId = $this->acl->getCurrentUserId(); @@ -141,7 +164,8 @@ public function deleteUserFromPoll(int $pollId, string $userId = '', bool $delet * @param string $userId user id of the user, the votes get deleted from. No user affects the current user * @param bool $deleteOnlyOrphaned - false deletes all votes of the specified user, true only the orphaned votes aka votes without an option */ - private function delete(int $pollId, string $userId, bool $deleteOnlyOrphaned = false): string { + private function delete(int $pollId, string $userId, bool $deleteOnlyOrphaned = false): string + { if ($deleteOnlyOrphaned) { $votes = $this->voteMapper->findOrphanedByPollandUser($pollId, $userId); foreach ($votes as $vote) { diff --git a/src/js/components/VoteTable/VoteItem.vue b/src/js/components/VoteTable/VoteItem.vue index 971e8e349..97123506b 100644 --- a/src/js/components/VoteTable/VoteItem.vue +++ b/src/js/components/VoteTable/VoteItem.vue @@ -102,6 +102,10 @@ export default { }) showSuccess(t('polls', 'Vote saved'), { timeout: 2000 }) } catch (e) { + if (e.response.status === 409 && e.response.data.message === 'Vote limit exceeded') { + showError(t('polls', 'Vote already booked out')) + return + } showError(t('polls', 'Error saving vote')) } }, diff --git a/src/js/store/modules/votes.js b/src/js/store/modules/votes.js index 045b0f421..d8761d5a2 100644 --- a/src/js/store/modules/votes.js +++ b/src/js/store/modules/votes.js @@ -112,6 +112,7 @@ const actions = { context.dispatch('list') context.dispatch('options/list', null, { root: true }) context.dispatch('poll/get', null, { root: true }) + throw error } else { Logger.error('Error setting vote', { error, payload }) throw error From 912561853e3b72f4f187dacb6776e6cabbd5f901 Mon Sep 17 00:00:00 2001 From: dartcafe Date: Sat, 28 Dec 2024 11:30:36 +0100 Subject: [PATCH 2/2] cs-fix Signed-off-by: dartcafe --- lib/Service/VoteService.php | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/lib/Service/VoteService.php b/lib/Service/VoteService.php index 32acd4c21..0e2d13758 100644 --- a/lib/Service/VoteService.php +++ b/lib/Service/VoteService.php @@ -21,8 +21,7 @@ use OCP\AppFramework\Db\DoesNotExistException; use OCP\EventDispatcher\IEventDispatcher; -class VoteService -{ +class VoteService { /** * @psalm-suppress PossiblyUnusedMethod */ @@ -33,15 +32,15 @@ public function __construct( private PollMapper $pollMapper, private Vote $vote, private VoteMapper $voteMapper, - ) {} + ) { + } /** * Read all votes of a poll based on the poll id and return list as array * * @return Vote[] */ - public function list(int $pollId): array - { + public function list(int $pollId): array { $poll = $this->pollMapper->find($pollId); $poll->request(Poll::PERMISSION_POLL_VIEW); @@ -55,8 +54,7 @@ public function list(int $pollId): array return $votes; } - private function checkLimits(Option $option): void - { + private function checkLimits(Option $option): void { // check, if the optionlimit is reached or exceeded, if one is set if ($option->getIsLockedByOptionLimit()) { throw new VoteLimitExceededException; @@ -68,8 +66,7 @@ private function checkLimits(Option $option): void return; } - private function checkVoteLimit(Option $option): void - { + private function checkVoteLimit(Option $option): void { // check, if the optionlimit is reached or exceeded, if one is set if ($option->getIsLockedByOptionLimit()) { throw new VoteLimitExceededException(); @@ -84,8 +81,7 @@ private function checkVoteLimit(Option $option): void /** * Set vote */ - public function set(int $optionId, string $setTo): ?Vote - { + public function set(int $optionId, string $setTo): ?Vote { $option = $this->optionMapper->find($optionId); $poll = $this->pollMapper->find($option->getPollId()); $poll->request(Poll::PERMISSION_VOTE_EDIT); @@ -139,8 +135,7 @@ public function set(int $optionId, string $setTo): ?Vote * @param string $userId user id of the user, the votes get deleted from * @param bool $deleteOnlyOrphaned - false deletes all votes of the specified user, true only the orphaned votes aka votes without an option */ - public function deleteUserFromPoll(int $pollId, string $userId = '', bool $deleteOnlyOrphaned = false): string - { + public function deleteUserFromPoll(int $pollId, string $userId = '', bool $deleteOnlyOrphaned = false): string { if ($userId === '') { // if no user set, use current user $userId = $this->acl->getCurrentUserId(); @@ -164,8 +159,7 @@ public function deleteUserFromPoll(int $pollId, string $userId = '', bool $delet * @param string $userId user id of the user, the votes get deleted from. No user affects the current user * @param bool $deleteOnlyOrphaned - false deletes all votes of the specified user, true only the orphaned votes aka votes without an option */ - private function delete(int $pollId, string $userId, bool $deleteOnlyOrphaned = false): string - { + private function delete(int $pollId, string $userId, bool $deleteOnlyOrphaned = false): string { if ($deleteOnlyOrphaned) { $votes = $this->voteMapper->findOrphanedByPollandUser($pollId, $userId); foreach ($votes as $vote) {