diff options
author | René Gieling <github@dartcafe.de> | 2020-07-07 18:33:39 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-07 18:33:39 +0300 |
commit | cf3e219160de4282f1f595a201bf97ba5dc2026b (patch) | |
tree | 5e8f48ca666181e8e7145e636bb0da8dba93412c /lib/Service | |
parent | 9466d5db224116ecb85693bea1cf6b5cfe4e7e26 (diff) | |
parent | 7f3efd71e43fe6775d73b5b2fb12bd0afaa30054 (diff) |
Merge pull request #966 from nextcloud/rest-poc
Adding REST API
Diffstat (limited to 'lib/Service')
-rw-r--r-- | lib/Service/CommentService.php | 144 | ||||
-rw-r--r-- | lib/Service/OptionService.php | 216 | ||||
-rw-r--r-- | lib/Service/PollService.php | 308 | ||||
-rw-r--r-- | lib/Service/ShareService.php | 226 | ||||
-rw-r--r-- | lib/Service/SubscriptionService.php | 131 | ||||
-rw-r--r-- | lib/Service/VoteService.php | 151 |
6 files changed, 1176 insertions, 0 deletions
diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php new file mode 100644 index 00000000..a1cd7131 --- /dev/null +++ b/lib/Service/CommentService.php @@ -0,0 +1,144 @@ +<?php +/** + * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> + * + * @author René Gieling <github@dartcafe.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Polls\Service; + +use \Exception; +use OCP\ILogger; + +use OCA\Polls\Exceptions\NotAuthorizedException; +use OCA\Polls\Db\Comment; +use OCA\Polls\Db\CommentMapper; +use OCA\Polls\Model\Acl; +use OCA\Polls\Service\AnonymizeService; + + + +class CommentService { + + private $comment; + private $commentMapper; + private $logger; + private $anonymizer; + private $acl; + + /** + * CommentService constructor. + * @param ILogger $logger + * @param CommentMapper $commentMapper + * @param Comment $comment + * @param AnonymizeService $anonymizer + * @param Acl $acl + */ + + public function __construct( + ILogger $logger, + CommentMapper $commentMapper, + Comment $comment, + AnonymizeService $anonymizer, + Acl $acl + ) { + $this->commentMapper = $commentMapper; + $this->comment = $comment; + $this->logger = $logger; + $this->anonymizer = $anonymizer; + $this->acl = $acl; + } + + /** + * get + * Read all comments of a poll based on the poll id and return list as array + * @NoAdminRequired + * @param integer $pollId + * @param string $token + * @return Array + */ + public function list($pollId = 0, $token = '') { + + if (!$this->acl->setPollIdOrToken($pollId, $token)->getAllowView()) { + throw new NotAuthorizedException; + } + + if (!$this->acl->getAllowSeeUsernames()) { + $this->anonymizer->set($this->acl->getPollId(), $this->acl->getUserId()); + return $this->anonymizer->getComments(); + } else { + return $this->commentMapper->findByPoll($this->acl->getPollId()); + } + } + + /** + * Write a new comment to the db and returns the new comment as array + * @NoAdminRequired + * @param string $message + * @param int $pollId + * @param string $token + * @return Comment + */ + public function add($pollId = 0, $message, $token = '') { + + if (!$this->acl->setPollIdOrToken($pollId, $token)->getAllowComment()) { + throw new NotAuthorizedException; + } + + try { + if ($this->acl->getAllowComment()) { + $this->comment = new Comment(); + $this->comment->setPollId($this->acl->getPollId()); + $this->comment->setUserId($this->acl->getUserId()); + $this->comment->setComment($message); + $this->comment->setDt(date('Y-m-d H:i:s')); + $this->comment = $this->commentMapper->insert($this->comment); + return $this->comment; + } else { + throw new NotAuthorizedException; + } + + } catch (\Exception $e) { + $this->logger->alert('Error writing comment for pollId ' . $pollId . ': '. $e); + throw new NotAuthorizedException($e); + } + + } + + /** + * delete + * Delete Comment + * @NoAdminRequired + * @param int $commentId + * @param string $token + * @return Comment + */ + public function delete($commentId, $token = '') { + $this->comment = $this->commentMapper->find($commentId); + + if ($this->acl->setPollIdOrToken($this->comment->getPollId(), $token)->getUserId() !== $this->acl->getUserId()) { + throw new NotAuthorizedException; + } + + $this->commentMapper->delete($this->comment); + return $this->comment; + + } + +} diff --git a/lib/Service/OptionService.php b/lib/Service/OptionService.php new file mode 100644 index 00000000..0afe4b8c --- /dev/null +++ b/lib/Service/OptionService.php @@ -0,0 +1,216 @@ +<?php +/** + * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> + * + * @author René Gieling <github@dartcafe.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Polls\Service; + +use Exception; +use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; + +use OCA\Polls\Db\Option; +use OCA\Polls\Db\OptionMapper; +use OCA\Polls\Service\LogService; +use OCA\Polls\Model\Acl; + +class OptionService { + + private $optionMapper; + private $option; + private $logService; + private $acl; + + /** + * OptionController constructor. + * @param OptionMapper $optionMapper + * @param Option $option + * @param LogService $logService + * @param Acl $acl + */ + + public function __construct( + OptionMapper $optionMapper, + Option $option, + LogService $logService, + Acl $acl + ) { + $this->optionMapper = $optionMapper; + $this->option = $option; + $this->logService = $logService; + $this->acl = $acl; + } + + /** + * Set properties from option array + * @NoAdminRequired + * @param Array $option + */ + private function set($option) { + + $this->option->setPollId($option['pollId']); + $this->option->setPollOptionText(trim(htmlspecialchars($option['pollOptionText']))); + $this->option->setTimestamp($option['timestamp']); + + if ($option['timestamp']) { + $this->option->setOrder($option['timestamp']); + } else { + $this->option->setOrder($option['order']); + } + + if ($option['confirmed']) { + // do not update confirmation date, if option is already confirmed + if (!$this->option->getConfirmed()) { + $this->option->setConfirmed(time()); + } + } else { + $this->option->setConfirmed(0); + } + } + + /** + * Get all options of given poll + * @NoAdminRequired + * @param integer $pollId + * @param string $token + * @return array Array of Option objects + */ + public function list($pollId = 0, $token = '') { + + if (!$this->acl->setPollIdOrToken($pollId, $token)->getAllowView()) { + throw new NotAuthorizedException; + } + + return $this->optionMapper->findByPoll($pollId); + + } + + + /** + * Add a new Option to poll + * @NoAdminRequired + * @param Array $option + * @return Option + */ + public function add($option) { + + if (!$this->acl->setPollId($option['pollId'])->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $this->option = new Option(); + $this->set($option); + $this->optionMapper->insert($this->option); + $this->logService->setLog($option['pollId'], 'addOption'); + + return $this->option; + } + + /** + * Remove a single option + * @NoAdminRequired + * @param Option $option + * @return array Array of Option objects + */ + public function delete($optionId) { + $this->option = $this->optionMapper->find($optionId); + + if (!$this->acl->setPollId($this->option->getPollId())->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $this->optionMapper->delete($this->option); + + return $this->option; + + } + + /** + * Update poll option + * @NoAdminRequired + * @param array $option + * @return Option + */ + public function update($option) { + if (!$this->acl->setPollId($option['pollId'])->getAllowEdit()) { + throw new NotAuthorizedException; + } + + try { + $this->option = $this->optionMapper->find($option['id']); + $this->set($option); + $this->optionMapper->update($this->option); + $this->logService->setLog($option['pollId'], 'updateOption'); + + return $this->option; + } catch (Exception $e) { + return new DoesNotExistException($e); + } + + } + + /** + * Set order by order of the given array + * @NoAdminRequired + * @param array $options + * @return array Array of Option objects + */ + public function reorder($pollId, $options) { + + if (!$this->acl->setPollId($pollId)->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $i = 0; + foreach ($options as $option) { + $this->option = $this->optionMapper->find($option['id']); + if ($pollId === intval($this->option->getPollId())) { + $this->option->setOrder(++$i); + $this->optionMapper->update($this->option); + } + } + + return $this->optionMapper->findByPoll($pollId); + + } + + /** + * Set order by order of the given array + * @NoAdminRequired + * @param integer $fromPollId + * @param integer $toPollId + * @return array Array of Option objects + */ + public function clone($fromPollId, $toPollId) { + + if (!$this->acl->setPollId($fromPollId)->getAllowView()) { + throw new NotAuthorizedException; + } + + foreach ($this->optionMapper->findByPoll($fromPollId) as $option) { + $option->setPollId($toPollId); + $this->optionMapper->insert($option); + } + + return $this->optionMapper->findByPoll($toPollId); + + } +} diff --git a/lib/Service/PollService.php b/lib/Service/PollService.php new file mode 100644 index 00000000..d23c8595 --- /dev/null +++ b/lib/Service/PollService.php @@ -0,0 +1,308 @@ +<?php +/** + * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> + * + * @author René Gieling <github@dartcafe.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + + namespace OCA\Polls\Service; + + use Exception; + use OCP\AppFramework\Db\DoesNotExistException; + use OCA\Polls\Exceptions\EmptyTitleException; + use OCA\Polls\Exceptions\InvalidAccessException; + use OCA\Polls\Exceptions\InvalidShowResultsException; + use OCA\Polls\Exceptions\InvalidPollTypeException; + use OCA\Polls\Exceptions\NotAuthorizedException; + + use OCP\ILogger; + + use OCA\Polls\Db\PollMapper; + use OCA\Polls\Db\Poll; + use OCA\Polls\Service\LogService; + use OCA\Polls\Model\Acl; + + class PollService { + + private $logger; + private $pollMapper; + private $poll; + private $logService; + private $acl; + + /** + * PollController constructor. + * @param ILogger $logger + * @param PollMapper $pollMapper + * @param Poll $poll + * @param LogService $logService + * @param Acl $acl + */ + + public function __construct( + ILogger $logger, + PollMapper $pollMapper, + Poll $poll, + LogService $logService, + Acl $acl + ) { + $this->logger = $logger; + $this->pollMapper = $pollMapper; + $this->poll = $poll; + $this->logService = $logService; + $this->acl = $acl; + } + + + /** + * list + * @NoAdminRequired + * @return array + */ + + public function list() { + if (!\OC::$server->getUserSession()->isLoggedIn()) { + throw new NotAuthorizedException; + } + + $pollList = []; + + $polls = $this->pollMapper->findAll(); + // TODO: Not the elegant way. Improvement neccessary + foreach ($polls as $poll) { + $combinedPoll = (object) array_merge( + (array) json_decode(json_encode($poll)), (array) json_decode(json_encode($this->acl->setPollId($poll->getId())))); + if ($combinedPoll->allowView) { + $pollList[] = $combinedPoll; + } + } + + return $pollList; + } + + /** + * get + * @NoAdminRequired + * @param integer $pollId + * @return array + */ + public function get($pollId) { + + if (!$this->acl->setPollId($pollId)->getAllowView()) { + throw new NotAuthorizedException; + } + + return $this->pollMapper->find($pollId); + + } + + /** + * get + * @NoAdminRequired + * @param integer $pollId + * @return array + */ + public function getByToken($token) { + + if (!$this->acl->setToken($token)->getAllowView()) { + throw new NotAuthorizedException; + } + + return $this->pollMapper->find($this->acl->getPollId()); + + } + + /** + * delete + * @NoAdminRequired + * @NoCSRFRequired + * @param integer $pollId + * @return Poll + */ + + public function delete($pollId) { + $this->poll = $this->pollMapper->find($pollId); + + if (!$this->acl->setPollId($pollId)->getAllowEdit()) { + throw new NotAuthorizedException; + } + + if ($this->poll->getDeleted()) { + $this->poll->setDeleted(0); + } else { + $this->poll->setDeleted(time()); + } + + $this->poll = $this->pollMapper->update($this->poll); + $this->logService->setLog($this->poll->getId(), 'deletePoll'); + + return $this->poll; + } + + /** + * deletePermanently + * @NoAdminRequired + * @NoCSRFRequired + * @param integer $pollId + * @return Poll + */ + + public function deletePermanently($pollId) { + $this->poll = $this->pollMapper->find($pollId); + + if (!$this->acl->setPollId($pollId)->getAllowEdit() || !$this->poll->getDeleted()) { + throw new NotAuthorizedException; + } + + return $this->pollMapper->delete($this->poll); + } + + /** + * write + * @NoAdminRequired + * @NoCSRFRequired + * @param string $type + * @param string $title + * @return Poll + */ + + public function add($type, $title) { + if (!\OC::$server->getUserSession()->isLoggedIn()) { + throw new NotAuthorizedException; + } + + // Validate valuess + if (!in_array($type, $this->getValidPollType())) { + throw new InvalidPollTypeException('Invalid poll type'); + } + + if (!$title) { + throw new EmptyTitleException('Title must not be empty'); + } + + $this->poll = new Poll(); + $this->poll->setType($type); + $this->poll->setCreated(time()); + $this->poll->setOwner(\OC::$server->getUserSession()->getUser()->getUID()); + $this->poll->setTitle($title); + $this->poll->setDescription(''); + $this->poll->setAccess('hidden'); + $this->poll->setExpire(0); + $this->poll->setAnonymous(0); + $this->poll->setFullAnonymous(0); + $this->poll->setAllowMaybe(0); + $this->poll->setVoteLimit(0); + $this->poll->setSettings(''); + $this->poll->setOptions(''); + $this->poll->setShowResults('always'); + $this->poll->setDeleted(0); + $this->poll->setAdminAccess(0); + $this->poll = $this->pollMapper->insert($this->poll); + + $this->logService->setLog($this->poll->getId(), 'addPoll'); + + return $this->poll; + } + + /** + * update + * @NoAdminRequired + * @NoCSRFRequired + * @param Array $poll + * @return Poll + */ + + public function update($pollId, $poll) { + + $this->poll = $this->pollMapper->find($pollId); + + if (!$this->acl->setPollId($this->poll->getId())->getAllowEdit()) { + throw new NotAuthorizedException; + } + + // Validate valuess + if (isset($poll['showResults']) && !in_array($poll['showResults'], $this->getValidShowResults())) { + throw new InvalidShowResultsException('Invalid value for prop showResults'); + } + + if (isset($poll['access']) && !in_array($poll['access'], $this->getValidAccess())) { + throw new InvalidAccessException('Invalid value for prop access '. $poll['access']); + } + + if (isset($poll['title']) && !$poll['title']) { + throw new EmptyTitleException('Title must not be empty'); + } + $this->poll->deserializeArray($poll); + + $this->pollMapper->update($this->poll); + $this->logService->setLog($this->poll->getId(), 'updatePoll'); + + return $this->poll; + } + + /** + * clone + * @NoAdminRequired + * @NoCSRFRequired + * @param integer $pollId + * @return Poll + */ + public function clone($pollId) { + + if (!$this->acl->setPollId($this->poll->getId())->getAllowView()) { + throw new NotAuthorizedException; + } + + $this->poll = $this->pollMapper->find($pollId); + + $this->poll->setCreated(time()); + $this->poll->setOwner(\OC::$server->getUserSession()->getUser()->getUID()); + $this->poll->setTitle('Clone of ' . $this->poll->getTitle()); + $this->poll->setDeleted(0); + $this->poll->setId(0); + + $this->poll = $this->pollMapper->insert($this->poll); + $this->logService->setLog($this->poll->getId(), 'addPoll'); + + $this->optionService->clone($pollId, $this->poll->getId()); + + return $this->poll; + + } + + public function getValidEnum() { + return [ + 'pollType' => $this->getValidPollType(), + 'access' => $this->getValidAccess(), + 'showResults' => $this->getValidShowResults() + ]; + } + + private function getValidPollType() { + return ['datePoll', 'textPoll']; + } + + private function getValidAccess() { + return ['hidden', 'public']; + } + + private function getValidShowResults() { + return ['always', 'expired', 'never']; + } +} diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php new file mode 100644 index 00000000..a7cf144b --- /dev/null +++ b/lib/Service/ShareService.php @@ -0,0 +1,226 @@ +<?php +/** + * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> + * + * @author René Gieling <github@dartcafe.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Polls\Service; + +use Exception; + +use OCP\Security\ISecureRandom; + +use OCA\Polls\Exceptions\NotAuthorizedException; +use OCA\Polls\Exceptions\InvalidUsername; + +use OCA\Polls\Db\Share; +use OCA\Polls\Db\ShareMapper; +use OCA\Polls\Service\MailService; +use OCA\Polls\Model\Acl; +use OCA\Polls\Controller\SystemController; + +class ShareService { + + private $shareMapper; + private $share; + private $systemController; + private $mailService; + private $acl; + + /** + * ShareController constructor. + * @param ShareMapper $shareMapper + * @param Share $share + * @param SystemController $systemController + * @param MailService $mailService + * @param Acl $acl + */ + public function __construct( + ShareMapper $shareMapper, + Share $share, + SystemController $systemController, + MailService $mailService, + Acl $acl + ) { + $this->shareMapper = $shareMapper; + $this->share = $share; + $this->systemController = $systemController; + $this->mailService = $mailService; + $this->acl = $acl; + } + + /** + * get + * Read all shares of a poll based on the poll id and return list as array + * @NoAdminRequired + * @param integer $pollId + * @return array + */ + public function list($pollId) { + if (!$this->acl->setPollId($pollId)->getAllowEdit()) { + throw new NotAuthorizedException; + } + + return $this->shareMapper->findByPoll($pollId); + + } + + /** + * getByToken + * Get pollId by token + * @NoAdminRequired + * @param string $token + * @return Share + */ + public function get($token) { + return $this->shareMapper->findByToken($token); + } + + /** + * Write a new share to the db and returns the new share as array + * @NoAdminRequired + * @depricated + * @param int $pollId + * @param string $share + * @return array + */ + // TODO: Replace with $this->add and separate sending invitations + public function write($pollId, $type, $userId, $userEmail = '') { + + if (!$this->acl->setPollId($pollId)->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $this->share = new Share(); + $this->share->setType($type); + $this->share->setPollId($pollId); + $this->share->setUserId($userId); + $this->share->setUserEmail($userEmail); + $this->share->setToken(\OC::$server->getSecureRandom()->generate( + 16, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + )); + + $this->share = $this->shareMapper->insert($this->share); + $sendResult = $this->mailService->sendInvitationMail($this->share->getToken()); + + return [ + 'share' => $this->share, + 'sendResult' => $sendResult + ]; + } + + /** + * Write a new share to the db and returns the new share as array + * @NoAdminRequired + * @param int $pollId + * @param string $share + * @return array + */ + public function add($pollId, $type, $userId, $userEmail = '') { + + if (!$this->acl->setPollId($pollId)->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $this->share = new Share(); + $this->share->setType($type); + $this->share->setPollId($pollId); + $this->share->setUserId($userId); + $this->share->setUserEmail($userEmail); + $this->share->setToken(\OC::$server->getSecureRandom()->generate( + 16, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + )); + + return $this->shareMapper->insert($this->share); + + } + + /** + * createPersonalShare + * Write a new share to the db and returns the new share as array + * @NoAdminRequired + * @param string $token + * @param string $userName + * @return Share + */ + public function createPersonalShare($token, $userName) { + $publicShare = $this->shareMapper->findByToken($token); + + // Return of validatePublicUsername is a DataResponse + $checkUsername = $this->systemController->validatePublicUsername($publicShare->getPollId(), $userName, $token); + + // if status is not 200, return DataResponse from validatePublicUsername + if ($checkUsername->getStatus() !== 200) { + throw new InvalidUsername; + } + + if ($publicShare->getType() === 'public') { + + + $this->share = new Share(); + $this->share->setToken(\OC::$server->getSecureRandom()->generate( + 16, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + )); + $this->share->setType('external'); + $this->share->setPollId($publicShare->getPollId()); + $this->share->setUserId($userName); + $this->share->setUserEmail(''); + return $this->shareMapper->insert($this->share); + + } elseif ($publicShare->getType() === 'email') { + + $publicShare->setType('external'); + $publicShare->setUserId($userName); + return $this->shareMapper->update($publicShare); + + } else { + throw new NotAuthorizedException; + } + } + + /** + * remove + * remove share + * @NoAdminRequired + * @param string $token + * @return Share + */ + + public function remove($token) { + $this->share = $this->shareMapper->findByToken($token); + if (!$this->acl->setPollId($this->share->getPollId())->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $this->shareMapper->delete($this->share); + + return $this->share; + + } +} diff --git a/lib/Service/SubscriptionService.php b/lib/Service/SubscriptionService.php new file mode 100644 index 00000000..f378e476 --- /dev/null +++ b/lib/Service/SubscriptionService.php @@ -0,0 +1,131 @@ +<?php +/** + * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> + * + * @author René Gieling <github@dartcafe.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Polls\Service; + +use Exception; +use OCA\Polls\Exceptions\NotAuthorizedException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\ILogger; + +use OCA\Polls\Db\Subscription; +use OCA\Polls\Db\SubscriptionMapper; +use OCA\Polls\Model\Acl; + +class SubscriptionService { + + private $acl; + private $subscriptionMapper; + private $logger; + + /** + * SubscriptionController constructor. + * @param SubscriptionMapper $subscriptionMapper + * @param ILogger $logger + * @param Acl $acl + */ + + public function __construct( + SubscriptionMapper $subscriptionMapper, + ILogger $logger, + Acl $acl + ) { + $this->subscriptionMapper = $subscriptionMapper; + $this->acl = $acl; + $this->logger = $logger; + } + + /** + * @NoAdminRequired + * @param integer $pollId + * @return array + */ + public function get($pollId) { + if (!$this->acl->setPollId($pollId)->getAllowView()) { + throw new NotAuthorizedException; + } + try { + return $this->subscriptionMapper->findByUserAndPoll($pollId, $this->acl->getUserId()); + } catch (MultipleObjectsReturnedException $e) { + // subscription should be unique. If duplicates are found resubscribe + // duplicates are removed in $this->set() + return $this->set($pollId, true); + } + + } + + /** + * @NoAdminRequired + * @param integer $pollId + * @return array + */ + public function set($pollId, $subscribed) { + if (!$this->acl->setPollId($pollId)->getAllowView()) { + throw new NotAuthorizedException; + } + try { + $subscription = $this->subscriptionMapper->findByUserAndPoll($pollId, $this->acl->getUserId()); + if (!$subscribed) { + $this->subscriptionMapper->delete($subscription); + return ['status' => 'Unsubscribed from poll ' . $pollId]; + } else { + // subscription already exists, just return the existing subscription + return ['status' => 'Subscribed to poll ' . $pollId]; + } + + } catch (DoesNotExistException $e){ + + if ($subscribed) { + $subscription = new Subscription(); + $subscription->setPollId($pollId); + $subscription->setUserId($this->acl->getUserId()); + + $this->subscriptionMapper->insert($subscription); + return ['status' => 'Subscribed to poll ' . $pollId]; + } else { + // subscription is not found, just approve the unsubscription + return ['status' => 'Unsubscribed from poll ' . $pollId]; + } + + } catch (MultipleObjectsReturnedException $e) { + // Duplicates should not exist but if found, fix it + // unsubscribe from all and resubscribe, if requested + $this->logger->debug('Multiple subscription (dulpicates) found'); + $this->subscriptionMapper->unsubscribe($pollId, $this->acl->getUserId()); + $this->logger->debug('Unsubscribed all for user ' . $this->acl->getUserId() . 'in poll' . $pollId); + if ($subscribed) { + $subscription = new Subscription(); + $subscription->setPollId($pollId); + $subscription->setUserId($this->acl->getUserId()); + $this->subscriptionMapper->insert($subscription); + $this->logger->debug('Added new subscription'); + return $subscription; + } else { + return ['status' => 'Unsubscribed from poll ' . $pollId]; + } + + } + + } +} diff --git a/lib/Service/VoteService.php b/lib/Service/VoteService.php new file mode 100644 index 00000000..4df01c70 --- /dev/null +++ b/lib/Service/VoteService.php @@ -0,0 +1,151 @@ +<?php +/** + * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> + * + * @author René Gieling <github@dartcafe.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Polls\Service; + +use Exception; +use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; + +use OCA\Polls\Db\Vote; +use OCA\Polls\Db\VoteMapper; +use OCA\Polls\Db\OptionMapper; +use OCA\Polls\Service\AnonymizeService; +use OCA\Polls\Service\LogService; +use OCA\Polls\Model\Acl; + +class VoteService { + + private $voteMapper; + private $vote; + private $optionMapper; + private $anonymizer; + private $logService; + private $acl; + + /** + * VoteController constructor. + * @param VoteMapper $voteMapper + * @param Vote $vote + * @param OptionMapper $optionMapper + * @param AnonymizeService $anonymizer + * @param LogService $logService + * @param Acl $acl + */ + public function __construct( + VoteMapper $voteMapper, + Vote $vote, + OptionMapper $optionMapper, + AnonymizeService $anonymizer, + LogService $logService, + Acl $acl + ) { + $this->voteMapper = $voteMapper; + $this->vote = $vote; + $this->optionMapper = $optionMapper; + $this->anonymizer = $anonymizer; + $this->logService = $logService; + $this->acl = $acl; + } + + /** + * Get all votes of given poll + * Read all votes of a poll based on the poll id and return list as array + * @NoAdminRequired + * @param integer $pollId + * @param string $token + * @return Vote + */ + public function list($pollId = 0, $token = '') { + if (!$this->acl->setPollIdOrToken($pollId, $token)->getAllowView()) { + throw new NotAuthorizedException; + } + + if (!$this->acl->getAllowSeeResults()) { + return $this->voteMapper->findByPollAndUser($this->acl->getpollId(), $this->acl->getUserId()); + } elseif (!$this->acl->getAllowSeeUsernames()) { + $this->anonymizer->set($this->acl->getpollId(), $this->acl->getUserId()); + return $this->anonymizer->getVotes(); + } else { + return $this->voteMapper->findByPoll($this->acl->getpollId()); + } + } + + /** + * set + * @NoAdminRequired + * @param integer $pollId + * @param Array $option + * @param string $setTo + * @param string $token + * @return Vote + */ + public function set($pollId = 0, $pollOptionText, $setTo, $token = '') { + + if (!$this->acl->setPollIdOrToken($pollId, $token)->getAllowVote()) { + throw new NotAuthorizedException; + } + + $option = $this->optionMapper->findByPollAndText($this->acl->getpollId(), $pollOptionText); + + try { + $this->vote = $this->voteMapper->findSingleVote($this->acl->getpollId(), $option->getPollOptionText(), $this->acl->getUserId()); + $this->vote->setVoteAnswer($setTo); + $this->voteMapper->update($this->vote); + + } catch (DoesNotExistException $e) { + // Vote does not exist, insert as new Vote + $this->vote = new Vote(); + + $this->vote->setPollId($this->acl->getpollId()); + $this->vote->setUserId($this->acl->getUserId()); + $this->vote->setVoteOptionText($option->getPollOptionText()); + $this->vote->setVoteOptionId($option->getId()); + $this->vote->setVoteAnswer($setTo); + $this->voteMapper->insert($this->vote); + + } finally { + $this->logService->setLog($this->vote->getPollId(), 'setVote', $this->vote->getUserId()); + return $this->vote; + } + } + + /** + * delete + * @NoAdminRequired + * @NoCSRFRequired + * @param integer $voteId + * @param string $userId + * @param integer $pollId + * @return Vote + */ + public function delete($pollId, $userId) { + + if (!$this->acl->setPollId($pollId)->getAllowEdit()) { + throw new NotAuthorizedException; + } + + $votes = $this->voteMapper->deleteByPollAndUser($pollId, $userId); + } + +} |