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