diff options
Diffstat (limited to 'lib')
31 files changed, 2611 insertions, 927 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 309c8f40..53922944 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -23,20 +23,6 @@ namespace OCA\Polls\AppInfo; -// use OCA\Polls\Controller\PageController; -// use OCA\Polls\Controller\ApiController; -// use OCA\Polls\Controller\CommentController; -// use OCA\Polls\Controller\PollController; -// use OCA\Polls\Controller\NotificationController; -// use OCA\Polls\Controller\OptionController; -// use OCA\Polls\Controller\VoteController; -// use OCA\Polls\Controller\ShareController; -// use OCA\Polls\Db\CommentMapper; -// use OCA\Polls\Db\OptionMapper; -// use OCA\Polls\Db\PollMapper; -// use OCA\Polls\Db\NotificationMapper; -// use OCA\Polls\Db\VoteMapper; -// use OCA\Polls\Db\ShareMapper; use OCP\AppFramework\App; use OCP\IContainer; diff --git a/lib/Controller/CommentApiController.php b/lib/Controller/CommentApiController.php new file mode 100644 index 00000000..6cc56bba --- /dev/null +++ b/lib/Controller/CommentApiController.php @@ -0,0 +1,120 @@ +<?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\Controller; + +use Exception; +use OCP\AppFramework\Db\DoesNotExistException; + +use OCP\IRequest; +use \OCP\IURLGenerator; +use OCP\AppFramework\ApiController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + +use OCA\Polls\Exceptions\NotAuthorizedException; + +use OCA\Polls\Service\CommentService; + + + +class CommentApiController extends ApiController { + + private $commentService; + /** + * CommentApiController constructor. + * @param string $appName + * @param IRequest $request + * @param CommentService $commentService + */ + + public function __construct( + string $appName, + IRequest $request, + CommentService $commentService + ) { + parent::__construct($appName, + $request, + 'POST, GET, DELETE', + 'Authorization, Content-Type, Accept', + 1728000); + $this->commentService = $commentService; + } + + /** + * get + * Read all comments of a poll based on the poll id and return list as array + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $pollId + * @return DataResponse + */ + public function list($pollId) { + try { + return new DataResponse(['comments' => $this->commentService->list($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll with id ' . $pollId . ' not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * Write a new comment to the db and returns the new comment as array + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param int $pollId + * @param string $message + * @return DataResponse + */ + public function add($pollId, $message) { + try { + return new DataResponse(['comment' => $this->commentService->add($pollId, $message)], Http::STATUS_CREATED); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll with id ' . $pollId . ' not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * Delete Comment + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param int $commentId + * @return DataResponse + */ + public function delete($commentId) { + try { + return new DataResponse(['comment' => $this->commentService->delete($commentId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Comment id ' . $commentId . ' does not exist'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + +} diff --git a/lib/Controller/CommentController.php b/lib/Controller/CommentController.php index 082bbbb3..6f240f05 100644 --- a/lib/Controller/CommentController.php +++ b/lib/Controller/CommentController.php @@ -26,68 +26,38 @@ namespace OCA\Polls\Controller; use Exception; use OCP\AppFramework\Db\DoesNotExistException; - use OCP\IRequest; use OCP\ILogger; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\IGroupManager; +use OCA\Polls\Exceptions\NotAuthorizedException; -use OCA\Polls\Db\Poll; -use OCA\Polls\Db\PollMapper; -use OCA\Polls\Db\Comment; -use OCA\Polls\Db\CommentMapper; -use OCA\Polls\Service\AnonymizeService; -use OCA\Polls\Model\Acl; +use OCA\Polls\Service\CommentService; class CommentController extends Controller { - private $userId; - private $mapper; - private $logger; - - private $groupManager; - private $pollMapper; - private $anonymizer; - private $acl; + private $commentService; /** * CommentController constructor. * @param string $appName - * @param $UserId - * @param CommentMapper $mapper - * @param IGroupManager $groupManager - * @param PollMapper $pollMapper - * @param AnonymizeService $anonymizer - * @param Acl $acl + * @param IRequest $request + * @param CommentService $commentService */ public function __construct( string $appName, - $userId, IRequest $request, - ILogger $logger, - CommentMapper $mapper, - IGroupManager $groupManager, - PollMapper $pollMapper, - AnonymizeService $anonymizer, - Acl $acl + CommentService $commentService ) { parent::__construct($appName, $request); - $this->userId = $userId; - $this->mapper = $mapper; - $this->logger = $logger; - $this->groupManager = $groupManager; - $this->pollMapper = $pollMapper; - $this->anonymizer = $anonymizer; - $this->acl = $acl; + $this->commentService = $commentService; } - /** * get * Read all comments of a poll based on the poll id and return list as array @@ -96,166 +66,56 @@ class CommentController extends Controller { * @param integer $pollId * @return DataResponse */ - public function get($pollId) { - - try { - if (!$this->acl->getFoundByToken()) { - $this->acl->setPollId($pollId); - } - - if (!$this->acl->getAllowSeeUsernames()) { - $this->anonymizer->set($pollId, $this->acl->getUserId()); - return new DataResponse((array) $this->anonymizer->getComments(), Http::STATUS_OK); - } else { - return new DataResponse((array) $this->mapper->findByPoll($pollId), Http::STATUS_OK); - } - - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } - - } - - /** - * getByToken - * Read all comments of a poll based on a share token and return list as array - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - * @param string $token - * @return DataResponse - */ - public function getByToken($token) { - - try { - $this->acl->setToken($token); - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } - - return $this->get($this->acl->getPollId()); - + public function list($pollId) { + return new DataResponse($this->commentService->list($pollId), Http::STATUS_OK); } + // /** + // * Read all comments of a poll based on a share token and return list as array + // * @NoAdminRequired + // * @NoCSRFRequired + // * @PublicPage + // * @param string $token + // * @return DataResponse + // */ + // public function getByToken($token) { + // return new DataResponse($this->commentService->get(0, $token), Http::STATUS_OK); + // } + // /** * Write a new comment to the db and returns the new comment as array * @NoAdminRequired - * @NoCSRFRequired + * @PublicPage * @param int $pollId - * @param string $userId * @param string $message - * @return DataResponse - */ - public function write($pollId, $userId, $message) { - if (!\OC::$server->getUserSession()->isLoggedIn() && !$this->acl->getFoundByToken()) { - $this->logger->alert('not allowed ' . json_encode(\OC::$server->getUserSession()->isLoggedIn())); - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - if (!$this->acl->getFoundByToken()) { - $this->acl->setPollId($pollId); - } - - if ($this->acl->getAllowComment()) { - $comment = new Comment(); - $comment->setPollId($pollId); - $comment->setUserId($userId); - $comment->setComment($message); - $comment->setDt(date('Y-m-d H:i:s')); - - - try { - $comment = $this->mapper->insert($comment); - } catch (\Exception $e) { - $this->logger->alert('conflict ' . json_encode($e)); - return new DataResponse($e, Http::STATUS_CONFLICT); - } - } else { - $this->logger->alert('unauthorized '); - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - return new DataResponse($comment, Http::STATUS_OK); - - } - - /** - * writeByToken - * @NoAdminRequired - * @PublicPage - * @NoCSRFRequired - * @param Array $option - * @param string $setTo * @param string $token * @return DataResponse */ - public function writeByToken($token, $message) { - + public function add($pollId, $message, $token) { try { - $this->acl->setToken($token); - return $this->write($this->acl->getPollId(), $this->acl->getUserId(), $message); - - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + return new DataResponse($this->commentService->add($pollId, $message, $token), Http::STATUS_OK); + } catch (Exception $e) { + return new DataResponse($e, Http::STATUS_UNAUTHORIZED); } - - } - /** - * delete * Delete Comment - * @NoCSRFRequired - * @NoAdminRequired - * @param int $pollId - * @param string $message - * @return DataResponse - */ - public function delete($comment) { - if (!\OC::$server->getUserSession()->isLoggedIn() && !$this->acl->getFoundByToken()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - if (!$this->acl->getFoundByToken()) { - $this->acl->setPollId($comment['pollId']); - } - - try { - if ($comment['userId'] === $this->acl->getUserId()) { - $comment = $this->mapper->find($comment['id']); - $comment = $this->mapper->delete($comment); - } - } catch (\Exception $e) { - return new DataResponse($e, Http::STATUS_CONFLICT); - } - - return new DataResponse(['comment' => $comment], Http::STATUS_OK); - - } - - /** - * writeByToken * @NoAdminRequired * @PublicPage - * @NoCSRFRequired - * @param Array $option - * @param string $setTo + * @param int $commentId * @param string $token * @return DataResponse */ - public function deleteByToken($token, $comment) { - + public function delete($commentId, $token) { try { - $this->acl->setToken($token); - return $this->delete($comment); - + return new DataResponse($this->commentService->delete($commentId, $token), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse($e, Http::STATUS_FORBIDDEN); } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + return new DataResponse($e, Http::STATUS_OK); } - - } } diff --git a/lib/Controller/OptionApiController.php b/lib/Controller/OptionApiController.php new file mode 100644 index 00000000..e3396a3e --- /dev/null +++ b/lib/Controller/OptionApiController.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\Controller; + +use Exception; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; +use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; + +use OCP\IRequest; +use OCP\AppFramework\ApiController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + + +use OCA\Polls\Service\OptionService; + +class OptionApiController extends ApiController { + + private $optionService; + + /** + * OptionApiController constructor. + * @param string $appName + * @param IRequest $request + * @param OptionService $optionService + */ + + public function __construct( + string $appName, + IRequest $request, + OptionService $optionService + ) { + parent::__construct($appName, + $request, + 'POST, PUT, GET, DELETE', + 'Authorization, Content-Type, Accept', + 1728000); + $this->optionService = $optionService; + } + + /** + * Get all options of given poll + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $pollId + * @return DataResponse + */ + public function list($pollId) { + try { + return new DataResponse(['options' => $this->optionService->list($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll with id ' . $pollId . ' not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + + /** + * Add a new Option to poll + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $pollId + * @param string $pollOptionText + * @param integer $timestamp + * @return DataResponse + */ + public function add($pollId, $pollOptionText = '', $timestamp = 0) { + $option = [ + 'pollId' => $pollId, + 'pollOptionText' => $pollOptionText, + 'timestamp' => $timestamp + ]; + + try { + return new DataResponse(['option' => $this->optionService->add($option)], Http::STATUS_CREATED); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll with id ' . $pollId . ' not found'], Http::STATUS_NOT_FOUND); + } catch (UniqueConstraintViolationException $e) { + return new DataResponse(['error' => 'Option exists'], Http::STATUS_CONFLICT); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + + /** + * Update poll option + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param array $option + * @return DataResponse + */ + public function update($option) { + try { + return new DataResponse(['option' => $this->optionService->update($option)], Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * Remove a single option + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $optionId + * @return DataResponse + */ + public function delete($optionId) { + try { + return new DataResponse(['option' => $this->optionService->delete($optionId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Option does not exist'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } +} diff --git a/lib/Controller/OptionController.php b/lib/Controller/OptionController.php index 0c20b768..0ec24092 100644 --- a/lib/Controller/OptionController.php +++ b/lib/Controller/OptionController.php @@ -24,98 +24,34 @@ namespace OCA\Polls\Controller; use Exception; -use OCP\AppFramework\Db\DoesNotExistException; use OCP\IRequest; -use OCP\ILogger; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\IGroupManager; -use OCP\Security\ISecureRandom; +use OCA\Polls\Exceptions\NotAuthorizedException; -use OCA\Polls\Db\Poll; -use OCA\Polls\Db\PollMapper; -use OCA\Polls\Db\Option; -use OCA\Polls\Db\OptionMapper; -use OCA\Polls\Service\LogService; -use OCA\Polls\Model\Acl; +use OCA\Polls\Service\OptionService; class OptionController extends Controller { - private $userId; - private $optionMapper; - private $options; - private $option; - private $groupManager; - private $pollMapper; - private $logger; - private $logService; - private $acl; + private $optionService; /** * OptionController constructor. * @param string $appName - * @param $UserId * @param IRequest $request - * @param ILogger $logger - * @param OptionMapper $optionMapper - * @param IGroupManager $groupManager - * @param PollMapper $pollMapper - * @param LogService $logService - * @param Acl $acl + * @param OptionService $optionService */ public function __construct( string $appName, - $UserId, IRequest $request, - OptionMapper $optionMapper, - Option $option, - IGroupManager $groupManager, - PollMapper $pollMapper, - ILogger $logger, - LogService $logService, - Acl $acl + OptionService $optionService ) { parent::__construct($appName, $request); - $this->userId = $UserId; - $this->optionMapper = $optionMapper; - $this->option = $option; - $this->groupManager = $groupManager; - $this->pollMapper = $pollMapper; - $this->logger = $logger; - $this->logService = $logService; - $this->acl = $acl; - } - - /** - * Set properties from option array - * @NoAdminRequired - * @param integer $pollId - * @return array Array of Option objects - */ - 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); - } + $this->optionService = $optionService; } /** @@ -123,22 +59,10 @@ class OptionController extends Controller { * @NoAdminRequired * @NoCSRFRequired * @param integer $pollId - * @return array Array of Option objects + * @return DataResponse */ - public function get($pollId) { - - try { - - if (!$this->acl->getFoundByToken()) { - $this->acl->setPollId($pollId); - } - - $this->options = $this->optionMapper->findByPoll($pollId); - - return new DataResponse($this->options, Http::STATUS_OK); - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } + public function list($pollId) { + return new DataResponse($this->optionService->list($pollId), Http::STATUS_OK); } @@ -152,64 +76,29 @@ class OptionController extends Controller { * @return DataResponse */ public function getByToken($token) { - - try { - $this->acl->setToken($token); - // return $this->get($this->acl->getPollId()); - $this->options = $this->optionMapper->findByPoll($this->acl->getPollId()); - return new DataResponse($this->options, Http::STATUS_OK); - - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } + return new DataResponse($this->optionService->list(0, $token), Http::STATUS_OK); } /** * Add a new Option to poll * @NoAdminRequired * @NoCSRFRequired - * @param Option $option + * @param array $option * @return DataResponse */ public function add($option) { - - if (!$this->acl->setPollId($option['pollId'])->getAllowEdit()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - try { - $this->option = new Option(); - $this->set($option); - $this->optionMapper->insert($this->option); - $this->logService->setLog($option['pollId'], 'addOption'); - return new DataResponse($this->option, Http::STATUS_OK); - } catch (Exception $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } + return new DataResponse($this->optionService->add($option), Http::STATUS_OK); } /** * Update poll option * @NoAdminRequired * @NoCSRFRequired - * @param Option $option + * @param array $option * @return DataResponse */ public function update($option) { - - if (!$this->acl->setPollId($option['pollId'])->getAllowEdit()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - try { - $this->option = $this->optionMapper->find($option['id']); - $this->set($option); - $this->optionMapper->update($this->option); - $this->logService->setLog($option['pollId'], 'updateOption'); - return new DataResponse($this->option, Http::STATUS_OK); - } catch (Exception $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } + return new DataResponse($this->optionService->update($option), Http::STATUS_OK); } /** @@ -220,49 +109,18 @@ class OptionController extends Controller { * @return DataResponse */ public function remove($option) { - try { - - if (!$this->acl->setPollId($option['pollId'])->getAllowEdit()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - $this->optionMapper->remove($option['id']); - $this->logService->setLog($option['pollId'], 'deleteOption'); - - return new DataResponse(array( - 'action' => 'deleted', - 'optionId' => $option['id'] - ), Http::STATUS_OK); - - } catch (Exception $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } - + return new DataResponse($this->optionService->delete($option['id']), Http::STATUS_OK); } /** * Set order by order of the given array * @NoAdminRequired * @NoCSRFRequired + * @param integer $pollId * @param Array $options * @return DataResponse */ public function reorder($pollId, $options) { - $i = 0; - - if (!$this->acl->setPollId($pollId)->getAllowEdit()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - 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->get($pollId); - + return new DataResponse($this->optionService->reorder($pollId, $options), Http::STATUS_OK); } } diff --git a/lib/Controller/PollApiController.php b/lib/Controller/PollApiController.php new file mode 100644 index 00000000..3c8acc9d --- /dev/null +++ b/lib/Controller/PollApiController.php @@ -0,0 +1,215 @@ +<?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\Controller; + + 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\IRequest; + use OCP\ILogger; + use OCP\AppFramework\ApiController; + use OCP\AppFramework\Http; + use OCP\AppFramework\Http\DataResponse; + + use OCA\Polls\Service\PollService; + + class PollApiController extends ApiController { + + private $logger; + private $pollService; + + /** + * PollController constructor. + * @param string $appName + * @param $userId + * @param IRequest $request + * @param ILogger $logger + * @param PollService $pollService + */ + + public function __construct( + string $appName, + IRequest $request, + ILogger $logger, + PollService $pollService + ) { + parent::__construct($appName, $request); + $this->logger = $logger; + $this->pollService = $pollService; + } + + + /** + * list + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * @return DataResponse + */ + + public function list() { + try { + return new DataResponse(['polls' => $this->pollService->list()], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + + /** + * get + * @NoAdminRequired + * @NoCSRFRequired + * @param integer $pollId + * @return array + */ + public function get($pollId) { + try { + return new DataResponse(['poll' => $this->pollService->get($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * write + * @NoAdminRequired + * @NoCSRFRequired + * @param Array $poll + * @return DataResponse + */ + + public function add($type, $title) { + try { + return new DataResponse(['poll' => $this->pollService->add($type, $title)], Http::STATUS_CREATED); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidPollTypeException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (EmptyTitleException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * write + * @NoAdminRequired + * @NoCSRFRequired + * @param Array $poll + * @return DataResponse + */ + + public function update($pollId, $poll) { + try { + return new DataResponse(['poll' => $this->pollService->update($pollId, $poll)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidAccessException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidShowResultsException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (EmptyTitleException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * delete + * @NoAdminRequired + * @NoCSRFRequired + * @param Array $poll + * @return DataResponse + */ + + public function delete($pollId) { + try { + return new DataResponse(['poll' => $this->pollService->delete($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * deletePermanently + * @NoAdminRequired + * @NoCSRFRequired + * @param Array $poll + * @return DataResponse + */ + + public function deletePermanently($pollId) { + try { + return new DataResponse(['poll' => $this->pollService->deletePermanently($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + + } + + /** + * clone + * @NoAdminRequired + * @NoCSRFRequired + * @param integer $pollId + * @return DataResponse + */ + public function clone($pollId) { + try { + return new DataResponse(['poll' => $this->pollService->clone($pollId)], Http::STATUS_CREATED); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * enum + * @NoAdminRequired + * @NoCSRFRequired + * @param Array $poll + * @return DataResponse + */ + + public function enum() { + return new DataResponse($this->pollService->getValidEnum(), Http::STATUS_OK); + } + + +} diff --git a/lib/Controller/PollController.php b/lib/Controller/PollController.php index b3494c4c..27f9c4be 100644 --- a/lib/Controller/PollController.php +++ b/lib/Controller/PollController.php @@ -23,107 +23,70 @@ namespace OCA\Polls\Controller; - use Exception; - use OCP\AppFramework\Db\DoesNotExistException; - - use OCP\IRequest; - use OCP\ILogger; - use OCP\IL10N; - use OCP\AppFramework\Controller; - use OCP\AppFramework\Http; - use OCP\AppFramework\Http\DataResponse; - - use OCP\IGroupManager; - use OCP\IUser; - use OCP\IUserManager; - use OCP\Security\ISecureRandom; - - use OCA\Polls\Db\Comment; - use OCA\Polls\Db\CommentMapper; - use OCA\Polls\Db\Poll; - use OCA\Polls\Db\PollMapper; - use OCA\Polls\Db\Option; - use OCA\Polls\Db\OptionMapper; - use OCA\Polls\Db\Share; - use OCA\Polls\Db\ShareMapper; - use OCA\Polls\Db\Vote; - use OCA\Polls\Db\VoteMapper; - use OCA\Polls\Service\LogService; - use OCA\Polls\Service\MailService; - use OCA\Polls\Service\AnonymizeService; - use OCA\Polls\Model\Acl; - - class PollController extends Controller { - - private $userId; - private $commentMapper; - private $pollMapper; - private $optionMapper; - private $shareMapper; - private $voteMapper; - private $trans; - private $logger; - private $groupManager; - private $userManager; - private $poll; - private $logService; - private $mailService; - private $anonymizer; - private $acl; +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\IRequest; +use OCP\ILogger; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + +use OCA\Polls\Service\PollService; +use OCA\Polls\Service\CommentService; +use OCA\Polls\Service\OptionService; +use OCA\Polls\Service\ShareService; +use OCA\Polls\Service\VoteService; +use OCA\Polls\Model\Acl; + +class PollController extends Controller { + + private $logger; + private $pollService; + private $commentService; + private $optionService; + private $shareService; + private $voteService; + private $acl; /** - * CommentController constructor. + * PollController constructor. * @param string $appName - * @param $userId * @param IRequest $request * @param ILogger $logger - * @param IL10N $trans - * @param OptionMapper $optionMapper - * @param PollMapper $pollMapper - * @param IGroupManager $groupManager - * @param IUserManager $userManager - * @param LogService $logService - * @param MailService $mailService - * @param AnonymizeService $anonymizer - * @param Acl $acl - */ + * @param PollService $pollService + * @param CommentService $commentService + * @param OptionService $optionService + * @param ShareService $shareService + * @param VoteService $voteService + * @param Acl $acl + */ public function __construct( - string $appName, - $userId, + string $appName, IRequest $request, ILogger $logger, - IL10N $trans, - CommentMapper $commentMapper, - OptionMapper $optionMapper, - PollMapper $pollMapper, - ShareMapper $shareMapper, - VoteMapper $voteMapper, - Poll $poll, - IGroupManager $groupManager, - IUserManager $userManager, - LogService $logService, - MailService $mailService, - AnonymizeService $anonymizer, - Acl $acl - ) { + PollService $pollService, + CommentService $commentService, + OptionService $optionService, + ShareService $shareService, + VoteService $voteService, + Acl $acl + ) { parent::__construct($appName, $request); - $this->userId = $userId; - $this->trans = $trans; - $this->commentMapper = $commentMapper; - $this->pollMapper = $pollMapper; - $this->optionMapper = $optionMapper; - $this->shareMapper = $shareMapper; - $this->voteMapper = $voteMapper; - $this->logger = $logger; - $this->groupManager = $groupManager; - $this->userManager = $userManager; - $this->poll = $poll; - $this->logService = $logService; - $this->mailService = $mailService; - $this->anonymizer = $anonymizer; - $this->acl = $acl; - } + $this->logger = $logger; + $this->pollService = $pollService; + $this->commentService = $commentService; + $this->optionService = $optionService; + $this->shareService = $shareService; + $this->voteService = $voteService; + $this->acl = $acl; + } /** @@ -134,29 +97,13 @@ */ public function list() { - if (\OC::$server->getUserSession()->isLoggedIn()) { - $pollList = []; - - try { - - $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 new DataResponse($pollList, Http::STATUS_OK); - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } - } else { - return new DataResponse([], Http::STATUS_OK); + try { + return new DataResponse($this->pollService->list(), Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } - } @@ -164,77 +111,61 @@ * get * @NoAdminRequired * @NoCSRFRequired + * @PublicPage * @param integer $pollId * @return array */ - public function get($pollId) { - - try { - if (!$this->acl->getFoundByToken()) { - $this->acl->setPollId($pollId); - } - - $this->poll = $this->pollMapper->find($pollId); - - if (!$this->acl->getAllowView()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - $options = $this->optionMapper->findByPoll($pollId); - - if ($this->acl->getAllowEdit()) { - $shares = $this->shareMapper->findByPoll($pollId); + public function get($pollId, $token) { + try { + if ($token) { + $poll = $this->pollService->getByToken($token); + $acl = $this->acl->setToken($token); } else { - $shares = []; + $poll = $this->pollService->get($pollId); + $acl = $this->acl->setPollId($pollId); } - if ($this->acl->getAllowSeeUsernames()) { - $comments = $this->commentMapper->findByPoll($pollId); - - if ($this->acl->getAllowSeeResults()) { - $votes = $this->voteMapper->findByPoll($pollId); - } else { - $votes = $this->voteMapper->findByPollAndUser($pollId, $this->acl->getUserId()); - } - } else { - $this->anonymizer->set($pollId, $this->acl->getUserId()); - $comments = $this->anonymizer->getComments(); - $votes = $this->anonymizer->getVotes(); + // $this->poll = $this->pollService->get($pollId, $token); + // return new DataResponse($this->pollService->get($pollId, $token), Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } - } + try { + $comments = $this->commentService->list($this->acl->getPollId(), $token); + } catch (Exception $e) { + $comments = []; + } - return new DataResponse([ - 'acl' => $this->acl, - 'comments' => $comments, - 'options' => $options, - 'poll' => $this->poll, - 'shares' => $shares, - 'votes' => $votes - ], Http::STATUS_OK); + try { + $options = $this->optionService->list($this->acl->getPollId(), $token); + } catch (Exception $e) { + $options = []; + } - } catch (DoesNotExistException $e) { - $this->logger->info('Poll ' . $pollId . ' not found!', ['app' => 'polls']); - return new DataResponse(null, Http::STATUS_NOT_FOUND); - } - } + try { + $votes = $this->voteService->list($this->acl->getPollId(), $token); + } catch (Exception $e) { + $votes = []; + } - /** - * getByToken - * Read all options of a poll based on a share token and return list as array - * @NoAdminRequired - * @PublicPage - * @NoCSRFRequired - * @param string $token - * @return DataResponse - */ - public function getByToken($token) { try { - return $this->get($this->acl->setToken($token)->getPollId()); - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + $shares = $this->shareService->list($this->acl->getPollId()); + } catch (Exception $e) { + $shares = []; } - } + return new DataResponse([ + 'acl' => $acl, + 'poll' => $poll, + 'comments' => $comments, + 'options' => $options, + 'shares' => $shares, + 'votes' => $votes + ], Http::STATUS_OK); + } /** * delete @@ -245,29 +176,12 @@ */ public function delete($pollId) { - try { - // Find existing poll - $this->poll = $this->pollMapper->find($pollId); - $this->acl->setPollId($this->poll->getId()); - - if (!$this->acl->getAllowEdit()) { - $this->logger->alert('Unauthorized delete attempt from user ' . $this->userId); - return new DataResponse(['message' => 'Unauthorized write attempt.'], Http::STATUS_UNAUTHORIZED); - } - - if ($this->poll->getDeleted()) { - $this->poll->setDeleted(0); - } else { - $this->poll->setDeleted(time()); - } - - $this->pollMapper->update($this->poll); - $this->logService->setLog($this->poll->getId(), 'deletePoll'); - return new DataResponse(['deleted' => $pollId], Http::STATUS_OK); - - } catch (Exception $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + return new DataResponse($this->pollService->delete($pollId), Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } } @@ -280,27 +194,34 @@ */ public function deletePermanently($pollId) { - try { - // Find existing poll - $this->poll = $this->pollMapper->find($pollId); - $this->acl->setPollId($this->poll->getId()); - - if (!$this->acl->getAllowEdit()) { - $this->logger->alert('Unauthorized delete attempt from user ' . $this->userId); - return new DataResponse(['message' => 'Unauthorized write attempt.'], Http::STATUS_UNAUTHORIZED); - } + return new DataResponse($this->pollService->deletePermanently($pollId), Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } - if (!$this->poll->getDeleted()) { - $this->logger->alert('user ' . $this->userId . ' trying to permanently delete active poll'); - return new DataResponse(['message' => 'Permanent deletion of active poll.'], Http::STATUS_CONFLICT); - } - $this->pollMapper->delete($this->poll); - return new DataResponse([], Http::STATUS_OK); + /** + * add + * @NoAdminRequired + * @NoCSRFRequired + * @param string $type + * @param string $title + * @return DataResponse + */ - } catch (Exception $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + public function add($type, $title) { + try { + return new DataResponse($this->pollService->add($type, $title), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidPollTypeException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (EmptyTitleException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } } @@ -308,55 +229,24 @@ * write * @NoAdminRequired * @NoCSRFRequired - * @param Array $poll + * @param integer $pollId + * @param array $poll * @return DataResponse */ - public function write($poll) { - + public function update($pollId, $poll) { try { - // Find existing poll - $this->poll = $this->pollMapper->find($poll['id']); - $this->acl->setPollId($this->poll->getId()); - if (!$this->acl->getAllowEdit()) { - $this->logger->alert('Unauthorized write attempt from user ' . $this->userId); - return new DataResponse(['message' => 'Unauthorized write attempt.'], Http::STATUS_UNAUTHORIZED); - } - - } catch (Exception $e) { - $this->poll = new Poll(); - - $this->poll->setType($poll['type']); - $this->poll->setOwner($this->userId); - $this->poll->setCreated(time()); - } finally { - $this->poll->setTitle($poll['title']); - $this->poll->setDescription($poll['description']); - $this->poll->setAccess($poll['access']); - $this->poll->setExpire($poll['expire']); - $this->poll->setAnonymous(intval($poll['anonymous'])); - $this->poll->setFullAnonymous(0); - $this->poll->setAllowMaybe(intval($poll['allowMaybe'])); - $this->poll->setVoteLimit(intval($poll['voteLimit'])); - $this->poll->setSettings(''); - $this->poll->setOptions(''); - $this->poll->setShowResults($poll['showResults']); - $this->poll->setDeleted($poll['deleted']); - $this->poll->setAdminAccess($poll['adminAccess']); - - if ($this->poll->getId() > 0) { - $this->pollMapper->update($this->poll); - $this->logService->setLog($this->poll->getId(), 'updatePoll'); - } else { - $this->pollMapper->insert($this->poll); - $this->logService->setLog($this->poll->getId(), 'addPoll'); - } - return $this->get($this->poll->getId()); - // $this->acl->setPollId($this->poll->getId()); - // return new DataResponse([ - // 'poll' => $this->poll, - // 'acl' => $this->acl - // ], Http::STATUS_OK); + return new DataResponse($this->pollService->update($pollId, $poll), Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidAccessException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidShowResultsException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (EmptyTitleException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } } @@ -368,40 +258,13 @@ * @return DataResponse */ public function clone($pollId) { - $this->poll = $this->pollMapper->find($pollId); - - $clonePoll = new Poll(); - $clonePoll->setOwner($this->userId); - $clonePoll->setCreated(time()); - $clonePoll->setTitle('Clone of ' . $this->poll->getTitle()); - $clonePoll->setDeleted(0); - - $clonePoll->setType($this->poll->getType()); - $clonePoll->setDescription($this->poll->getDescription()); - $clonePoll->setAccess($this->poll->getAccess()); - $clonePoll->setExpire($this->poll->getExpire()); - $clonePoll->setAnonymous(intval($this->poll->getAnonymous())); - $clonePoll->setFullAnonymous(0); - $clonePoll->setAllowMaybe(intval($this->poll->getAllowMaybe())); - $clonePoll->setVoteLimit(intval($this->poll->getVoteLimit())); - $clonePoll->setSettings(''); - $clonePoll->setOptions(''); - $clonePoll->setShowResults($this->poll->getShowResults()); - $clonePoll->setAdminAccess($this->poll->getAdminAccess()); - - $this->pollMapper->insert($clonePoll); - $this->logService->setLog($clonePoll->getId(), 'addPoll'); - - foreach ($this->optionMapper->findByPoll($pollId) as $option) { - $newOption = new Option(); - $newOption->setPollId($clonePoll->getId()); - $newOption->setPollOptionText($option->getPollOptionText()); - $newOption->setTimestamp($option->getTimestamp()); - - $this->optionMapper->insert($newOption); + try { + return new DataResponse($this->pollService->clone($pollId), Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Poll not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } - return new DataResponse(['pollId' => $clonePoll->getId()], Http::STATUS_OK); - } } diff --git a/lib/Controller/ShareApiController.php b/lib/Controller/ShareApiController.php new file mode 100644 index 00000000..cceb7aa6 --- /dev/null +++ b/lib/Controller/ShareApiController.php @@ -0,0 +1,141 @@ +<?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\Controller; + +use Exception; +use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; +use OCA\Polls\Exceptions\InvalidUsername; + + +use OCP\IRequest; +use OCP\AppFramework\ApiController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + +use OCA\Polls\Service\ShareService; + +class ShareApiController extends ApiController { + + private $shareService; + + /** + * ShareController constructor. + * @param string $appName + * @param string $userId + * @param IRequest $request + * @param ShareService $shareService + */ + public function __construct( + string $appName, + IRequest $request, + ShareService $shareService + ) { + parent::__construct($appName, + $request, + 'POST, PUT, GET, DELETE', + 'Authorization, Content-Type, Accept', + 1728000); + $this->shareService = $shareService; + } + + /** + * list + * Read all shares of a poll based on the poll id and return list as array + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $pollId + * @return DataResponse + */ + public function list($pollId) { + try { + return new DataResponse(['shares' => $this->shareService->list($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'No shares for poll with id ' . $pollId . ' not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * get share by token + * Get pollId by token + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * @param string $token + * @return DataResponse + */ + public function get($token) { + try { + return new DataResponse(['share' => $this->shareService->get($token)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Token ' . $token . ' not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * Write a new share to the db and returns the new share as array + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param int $pollId + * @param string $type + * @param string $userId + * @param string $userEmail + * @return DataResponse + */ + public function add($pollId, $type, $userId = '', $userEmail = '') { + try { + return new DataResponse(['share' => $this->shareService->add($pollId, $type, $userId, $userEmail)], Http::STATUS_CREATED); + } catch (\Exception $e) { + return new DataResponse(['error' => $e], Http::STATUS_CONFLICT); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + + } + + /** + * delete share + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param string $token + * @return DataResponse + */ + + public function delete($token) { + try { + return new DataResponse(['share' => $this->shareService->remove($token)], Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (Exception $e) { + return new DataResponse($e, Http::STATUS_NOT_FOUND); + } + } +} diff --git a/lib/Controller/ShareController.php b/lib/Controller/ShareController.php index 99746a78..aa80cc3d 100644 --- a/lib/Controller/ShareController.php +++ b/lib/Controller/ShareController.php @@ -25,6 +25,8 @@ namespace OCA\Polls\Controller; use Exception; use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; +use OCA\Polls\Exceptions\InvalidUsername; use OCP\IRequest; @@ -33,105 +35,36 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\Security\ISecureRandom; -use OCA\Polls\Db\Poll; use OCA\Polls\Model\Acl; -use OCA\Polls\Db\PollMapper; -use OCA\Polls\Db\Share; -use OCA\Polls\Db\ShareMapper; -use OCA\Polls\Service\MailService; -// TODO: Change to Service -use OCA\Polls\Controller\SystemController; +use OCA\Polls\Service\ShareService; class ShareController extends Controller { private $logger; - private $acl; - private $mapper; + private $shareService; private $userId; - private $pollMapper; - private $systemController; - private $mailService; - /** * ShareController constructor. * @param string $appName * @param string $userId * @param IRequest $request * @param ILogger $logger - * @param ShareMapper $mapper - * @param PollMapper $pollMapper - * @param SystemController $systemController - * @param MailService $mailService - * @param Acl $acl + * @param ShareService $shareService */ public function __construct( string $appName, $userId, IRequest $request, ILogger $logger, - ShareMapper $mapper, - PollMapper $pollMapper, - SystemController $systemController, - MailService $mailService, - Acl $acl + ShareService $shareService ) { parent::__construct($appName, $request); $this->logger = $logger; $this->userId = $userId; - $this->mapper = $mapper; - $this->pollMapper = $pollMapper; - $this->systemController = $systemController; - $this->mailService = $mailService; - $this->acl = $acl; - } - - /** - * getByToken - * Get pollId by token - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - * @param string $token - * @return DataResponse - */ - public function get($token) { - try { - $share = $this->mapper->findByToken($token); - return new DataResponse($share, Http::STATUS_OK); - - } catch (DoesNotExistException $e) { - return new DataResponse(null, Http::STATUS_NOT_FOUND); - } - } - - /** - * get - * Read all shares of a poll based on the poll id and return list as array - * @NoAdminRequired - * @NoCSRFRequired - * @param integer $pollId - * @return DataResponse - */ - public function getShares($pollId) { - if ($this->acl->setPollId($pollId)->getAllowEdit()) { - try { - $shares = $this->mapper->findByPoll($pollId); - return new DataResponse((array) $shares, Http::STATUS_OK); - - } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); - } - - } else { - $this->logger->alert('no access'); - - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - + $this->shareService = $shareService; } /** @@ -139,36 +72,20 @@ class ShareController extends Controller { * @NoAdminRequired * @NoCSRFRequired * @param int $pollId - * @param string $message + * @param Array $share * @return DataResponse */ - public function write($pollId, $share) { - $this->acl->setPollId($pollId); - if (!$this->acl->getAllowEdit()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - - $newShare = new Share(); - $newShare->setType($share['type']); - $newShare->setPollId($share['pollId']); - $newShare->setUserId($share['userId']); - $newShare->setUserEmail(isset($share['userEmail']) ? $share['userEmail'] : ''); - $newShare->setToken(\OC::$server->getSecureRandom()->generate( - 16, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER - )); - + public function add($pollId, $share) { try { - $newShare = $this->mapper->insert($newShare); - $sendResult = $this->mailService->sendInvitationMail($newShare->getToken()); - - return new DataResponse([ - 'share' => $newShare, - 'sendResult' => $sendResult - ], Http::STATUS_OK); - + $return = $this->shareService->write( + $pollId, + $share['type'], + $share['userId'], + isset($share['userEmail']) ? $share['userEmail'] : '' + ); + return new DataResponse($return, Http::STATUS_CREATED); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (\Exception $e) { return new DataResponse($e, Http::STATUS_CONFLICT); } @@ -181,50 +98,18 @@ class ShareController extends Controller { * @NoAdminRequired * @PublicPage * @NoCSRFRequired - * @param int $pollId - * @param string $message + * @param string $token + * @param string $userName * @return DataResponse */ public function createPersonalShare($token, $userName) { try { - $publicShare = $this->mapper->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) { - return $checkUsername; - } - - if ($publicShare->getType() === 'public') { - - $userShare = new Share(); - $userShare->setToken(\OC::$server->getSecureRandom()->generate( - 16, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER - )); - $userShare->setType('external'); - $userShare->setPollId($publicShare->getPollId()); - $userShare->setUserId($userName); - $userShare->setUserEmail(''); - $userShare = $this->mapper->insert($userShare); - return new DataResponse($userShare, Http::STATUS_OK); - - } elseif ($publicShare->getType() === 'email') { - - $publicShare->setType('external'); - $publicShare->setUserId($userName); - $this->mapper->update($publicShare); - return new DataResponse($publicShare, Http::STATUS_OK); - - } else { - return new DataResponse(['message'=> 'Wrong share type: ' . $publicShare->getType()], Http::STATUS_FORBIDDEN); - } - + return new DataResponse($this->shareService->createPersonalShare($token, $userName), Http::STATUS_CREATED); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } catch (InvalidUsername $e) { + return new DataResponse(['error' => $userName . ' is not valid'], Http::STATUS_CONFLICT); } catch (DoesNotExistException $e) { // return forbidden in all not catched error cases return new DataResponse($e, Http::STATUS_FORBIDDEN); @@ -240,19 +125,14 @@ class ShareController extends Controller { * @return DataResponse */ - public function remove($share) { + public function delete($share) { try { - if ($this->acl->setPollId($share['pollId'])->getAllowEdit()) { - $this->mapper->remove($share['id']); - - return new DataResponse(array( - 'action' => 'deleted', - 'shareId' => $share['id'] - ), Http::STATUS_OK); - } else { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - + return new DataResponse(array( + 'action' => 'deleted', + 'shareId' => $this->shareService->remove($share['token'])->getId() + ), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (Exception $e) { return new DataResponse($e, Http::STATUS_NOT_FOUND); } diff --git a/lib/Controller/SubscriptionApiController.php b/lib/Controller/SubscriptionApiController.php new file mode 100644 index 00000000..3a23d403 --- /dev/null +++ b/lib/Controller/SubscriptionApiController.php @@ -0,0 +1,118 @@ +<?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\Controller; + +use Exception; +use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; + +use OCP\IRequest; +use OCP\ILogger; + +use OCP\AppFramework\ApiController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + +use OCA\Polls\Service\SubscriptionService; + +class SubscriptionApiController extends ApiController { + + private $userId; + private $subscriptionService; + private $logger; + + /** + * SubscriptionController constructor. + * @param string $appName + * @param $UserId + * @param SubscriptionService $subscriptionService + * @param IRequest $request + * @param ILogger $logger + */ + + public function __construct( + string $appName, + $userId, + SubscriptionService $subscriptionService, + IRequest $request, + ILogger $logger + + ) { + parent::__construct($appName, + $request, + 'PUT, GET, DELETE', + 'Authorization, Content-Type, Accept', + 1728000); + $this->userId = $userId; + $this->subscriptionService = $subscriptionService; + $this->logger = $logger; + } + + /** + * @NoAdminRequired + * CORS + * @NoCSRFRequired + * @param integer $pollId + * @return DataResponse + */ + public function get($pollId) { + try { + $this->subscriptionService->get($pollId); + return new DataResponse(['status' => 'Subscribed to poll ' . $pollId], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['status' => 'Not subscribed to poll ' . $pollId], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $pollId + */ + public function subscribe($pollId) { + try { + $this->subscriptionService->set($pollId, true); + return new DataResponse(['status' => 'Subscribed to poll ' . $pollId], Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + /** + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @param integer $pollId + */ + public function unsubscribe($pollId) { + try { + $this->subscriptionService->set($pollId, false); + return new DataResponse(['status' => 'Unsubscribed from poll ' . $pollId], Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } +} diff --git a/lib/Controller/SubscriptionController.php b/lib/Controller/SubscriptionController.php index 8a5bf445..e90f4a66 100644 --- a/lib/Controller/SubscriptionController.php +++ b/lib/Controller/SubscriptionController.php @@ -25,29 +25,27 @@ namespace OCA\Polls\Controller; use Exception; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCA\Polls\Exceptions\NotAuthorizedException; use OCP\IRequest; use OCP\ILogger; - use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCA\Polls\Db\Subscription; -use OCA\Polls\Db\SubscriptionMapper; +use OCA\Polls\Service\SubscriptionService; class SubscriptionController extends Controller { private $userId; - private $mapper; + private $subscriptionService; private $logger; /** * SubscriptionController constructor. * @param string $appName * @param $UserId - * @param SubscriptionMapper $mapper + * @param SubscriptionService $subscriptionService * @param IRequest $request * @param ILogger $logger */ @@ -55,14 +53,14 @@ class SubscriptionController extends Controller { public function __construct( string $appName, $userId, - SubscriptionMapper $mapper, + SubscriptionService $subscriptionService, IRequest $request, ILogger $logger ) { parent::__construct($appName, $request); $this->userId = $userId; - $this->mapper = $mapper; + $this->subscriptionService = $subscriptionService; $this->logger = $logger; } @@ -73,19 +71,13 @@ class SubscriptionController extends Controller { * @return DataResponse */ public function get($pollId) { - - if (!\OC::$server->getUserSession()->isLoggedIn()) { - return new DataResponse(null, Http::STATUS_UNAUTHORIZED); - } - try { - $this->mapper->findByUserAndPoll($pollId, $this->userId); - } catch (MultipleObjectsReturnedException $e) { - // should not happen, but who knows + return new DataResponse($this->subscriptionService->get($pollId), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (DoesNotExistException $e) { - return new DataResponse(null, Http::STATUS_NOT_FOUND); + return new DataResponse(['status' => 'Not subscribed'], Http::STATUS_NOT_FOUND); } - return new DataResponse(null, Http::STATUS_OK); } /** @@ -94,15 +86,10 @@ class SubscriptionController extends Controller { * @param integer $pollId */ public function set($pollId, $subscribed) { - if ($subscribed) { - $subscription = new Subscription(); - $subscription->setPollId($pollId); - $subscription->setUserId($this->userId); - $this->mapper->insert($subscription); - return true; - } else { - $this->mapper->unsubscribe($pollId, $this->userId); - return false; + try { + return new DataResponse($this->subscriptionService->set($pollId, $subscribed), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } } } diff --git a/lib/Controller/SystemController.php b/lib/Controller/SystemController.php index 9c8326cf..d4c15963 100644 --- a/lib/Controller/SystemController.php +++ b/lib/Controller/SystemController.php @@ -148,8 +148,9 @@ class SystemController extends Controller { } if ($getUsers) { - foreach ($this->userManager->searchDisplayName($query) as $user) { - if (!in_array($user->getUID(), $skipUsers)) { + $users = $this->userManager->searchDisplayName($query); + foreach ($users as $user) { + if (!in_array($user->getUID(), $skipUsers) && $user->isEnabled()) { $list[] = [ 'id' => $user->getUID(), 'user' => $user->getUID(), diff --git a/lib/Controller/VoteApiController.php b/lib/Controller/VoteApiController.php new file mode 100644 index 00000000..21d7762d --- /dev/null +++ b/lib/Controller/VoteApiController.php @@ -0,0 +1,105 @@ +<?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\Controller; + +use Exception; +use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; + +use OCP\IRequest; +use OCP\ILogger; +use OCP\AppFramework\ApiController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + +use OCA\Polls\Service\VoteService; + +class VoteApiController extends ApiController { + + private $logger; + private $voteService; + + /** + * VoteController constructor. + * @param string $appName + * @param IRequest $request + * @param ILogger $logger + * @param VoteService $voteService + */ + public function __construct( + string $appName, + IRequest $request, + ILogger $logger, + VoteService $voteService + ) { + parent::__construct($appName, + $request, + 'PUT, GET, DELETE', + 'Authorization, Content-Type, Accept', + 1728000); + $this->voteService = $voteService; + $this->logger = $logger; + } + + /** + * Get all votes of given poll + * Read all votes of a poll based on the poll id and return list as array + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * @param integer $pollId + * @return DataResponse + */ + public function list($pollId) { + try { + return new DataResponse(['votes' => $this->voteService->list($pollId)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'No votes'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + } + + /** + * set + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * @param integer $pollId + * @param Array $option + * @param string $userId + * @param string $setTo + * @return DataResponse + */ + public function set($pollId, $pollOptionText, $setTo) { + try { + return new DataResponse(['vote' => $this->voteService->set($pollId, $pollOptionText, $setTo)], Http::STATUS_OK); + } catch (DoesNotExistException $e) { + return new DataResponse(['error' => 'Option not found'], Http::STATUS_NOT_FOUND); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); + } + + } +} diff --git a/lib/Controller/VoteController.php b/lib/Controller/VoteController.php index ad8936bd..f666c004 100644 --- a/lib/Controller/VoteController.php +++ b/lib/Controller/VoteController.php @@ -23,77 +23,41 @@ namespace OCA\Polls\Controller; -use Exception; +// use Exception; use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Polls\Exceptions\NotAuthorizedException; - -use OCP\IRequest; use OCP\ILogger; +use OCP\IRequest; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\IGroupManager; +use OCA\Polls\Service\VoteService; -use OCA\Polls\Db\Poll; -use OCA\Polls\Db\PollMapper; -use OCA\Polls\Db\Vote; -use OCA\Polls\Db\VoteMapper; -use OCA\Polls\Db\Share; -use OCA\Polls\Db\ShareMapper; -use OCA\Polls\Service\AnonymizeService; -use OCA\Polls\Service\LogService; -use OCA\Polls\Model\Acl; class VoteController extends Controller { - private $userId; + private $voteService; private $logger; - private $mapper; - private $groupManager; - private $pollMapper; - private $shareMapper; - private $anonymizer; - private $logService; - private $acl; /** * VoteController constructor. * @param string $appName - * @param $userId * @param IRequest $request * @param ILogger $logger - * @param VoteMapper $mapper - * @param IGroupManager $groupManager - * @param PollMapper $pollMapper - * @param ShareMapper $shareMapper - * @param AnonymizeService $anonymizer - * @param LogService $logService - * @param Acl $acl + * @param VoteService $voteService + */ public function __construct( string $appName, - $UserId, - IRequest $request, ILogger $logger, - VoteMapper $mapper, - IGroupManager $groupManager, - PollMapper $pollMapper, - ShareMapper $shareMapper, - AnonymizeService $anonymizer, - LogService $logService, - Acl $acl + IRequest $request, + VoteService $voteService ) { parent::__construct($appName, $request); - $this->userId = $UserId; - $this->mapper = $mapper; $this->logger = $logger; - $this->groupManager = $groupManager; - $this->pollMapper = $pollMapper; - $this->shareMapper = $shareMapper; - $this->anonymizer = $anonymizer; - $this->logService = $logService; - $this->acl = $acl; + $this->voteService = $voteService; } /** @@ -105,26 +69,13 @@ class VoteController extends Controller { * @return DataResponse */ public function get($pollId) { - try { - - if (!$this->acl->getFoundByToken()) { - $this->acl->setPollId($pollId); - } - - if (!$this->acl->getAllowSeeResults()) { - return new DataResponse((array) $this->mapper->findByPollAndUser($pollId, $this->acl->getUserId()), Http::STATUS_OK); - } elseif (!$this->acl->getAllowSeeUsernames()) { - $this->anonymizer->set($pollId, $this->acl->getUserId()); - return new DataResponse((array) $this->anonymizer->getVotes(), Http::STATUS_OK); - } else { - return new DataResponse((array) $this->mapper->findByPoll($pollId), Http::STATUS_OK); - } - + return new DataResponse($this->voteService->list($pollId), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + return new DataResponse(['error' => 'No votes'], Http::STATUS_NOT_FOUND); } - } /** @@ -137,28 +88,13 @@ class VoteController extends Controller { * @param string $setTo * @return DataResponse */ - public function set($pollId, $option, $userId, $setTo) { - + public function set($pollId, $option, $setTo) { try { - $vote = $this->mapper->findSingleVote($pollId, $option['pollOptionText'], $userId); - $vote->setVoteAnswer($setTo); - $this->mapper->update($vote); - + return new DataResponse($this->voteService->set($pollId, $option['pollOptionText'], $setTo), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (DoesNotExistException $e) { - // Vote does not exist, insert as new Vote - $vote = new Vote(); - - $vote->setPollId($pollId); - $vote->setUserId($userId); - $vote->setVoteOptionText($option['pollOptionText']); - $vote->setVoteOptionId($option['id']); - $vote->setVoteAnswer($setTo); - - $this->mapper->insert($vote); - - } finally { - $this->logService->setLog($vote->getPollId(), 'setVote', $vote->getUserId()); - return new DataResponse($vote, Http::STATUS_OK); + return new DataResponse(['error' => 'Option not found'], Http::STATUS_NOT_FOUND); } } @@ -172,27 +108,13 @@ class VoteController extends Controller { * @param integer $pollId * @return DataResponse */ - public function delete($voteId = 0, $userId = '', $pollId = 0) { - $this->logger->alert('Deleting vote no. ' . $voteId); - + public function delete($userId, $pollId) { try { - if ($voteId) { - $vote = $this->mapper->delete($voteId); - $this->logger->alert('Deleting vote no. ' . $voteId); - return new DataResponse(null, Http::STATUS_OK); - } elseif ($pollId && $userId) { - $votes = $this->mapper->deleteByPollAndUser($pollId, $userId); - $this->logger->alert('Deleting votes from ' . $userId . ' in poll ' . $pollId); - return new DataResponse(null, Http::STATUS_OK); - } elseif ($pollId) { - $votes = $this->mapper->deleteByPoll($pollId); - $this->logger->alert('Deleting all votes in poll ' . $pollId); - return new DataResponse(null, Http::STATUS_OK); - } else { - return DataResponse(null, Http::STATUS_NOT_FOUND); - } + return new DataResponse($this->voteService->delete($pollId, $userId), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (DoesNotExistException $e) { - return DataResponse(null, Http::STATUS_NOT_FOUND); + return new DataResponse(['error' => ''], Http::STATUS_NOT_FOUND); } } @@ -212,13 +134,13 @@ class VoteController extends Controller { */ public function setByToken($option, $setTo, $token) { try { - $this->acl->setToken($token); + return new DataResponse($this->voteService->set(0, $option['pollOptionText'], $setTo, $token), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + return new DataResponse(['error' => 'Option not found'], Http::STATUS_NOT_FOUND); } - return $this->set($this->acl->getPollId(), $option, $this->acl->getUserId(), $setTo); - } /** @@ -231,15 +153,14 @@ class VoteController extends Controller { * @return DataResponse */ public function getByToken($token) { - try { - $this->acl->setToken($token); + return new DataResponse($this->voteService->list(null, $token), Http::STATUS_OK); + } catch (NotAuthorizedException $e) { + return new DataResponse(['error' => $e->getMessage()], $e->getStatus()); } catch (DoesNotExistException $e) { - return new DataResponse($e, Http::STATUS_NOT_FOUND); + return new DataResponse(['error' => 'No votes'], Http::STATUS_NOT_FOUND); } - return $this->get($this->acl->getPollId()); - } } diff --git a/lib/Db/OptionMapper.php b/lib/Db/OptionMapper.php index 07f024d9..3044c90c 100644 --- a/lib/Db/OptionMapper.php +++ b/lib/Db/OptionMapper.php @@ -76,6 +76,28 @@ class OptionMapper extends QBMapper { } /** + * @param int $pollId + * @throws \OCP\AppFramework\Db\DoesNotExistException if not found + * @return array + */ + + public function findByPollAndText($pollId, $pollOptionText) { + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from($this->getTableName()) + ->where( + $qb->expr()->eq('poll_id', $qb->createNamedParameter($pollId, IQueryBuilder::PARAM_INT)) + ) + ->andWhere( + $qb->expr()->eq('poll_option_text', $qb->createNamedParameter($pollOptionText, IQueryBuilder::PARAM_STR)) + ) + ->orderBy('order', 'ASC'); + + return $this->findEntity($qb); + } + + /** * @param int $optionId */ public function remove($optionId) { diff --git a/lib/Db/Poll.php b/lib/Db/Poll.php index 55b12fa2..8fa2d056 100644 --- a/lib/Db/Poll.php +++ b/lib/Db/Poll.php @@ -135,6 +135,20 @@ class Poll extends Entity implements JsonSerializable { ]; } + public function deserializeArray($array) { + $this->setTitle(isset($array['title']) ? $array['title'] : $this->getTitle()); + $this->setDescription(isset($array['description']) ? $array['description'] : $this->getDescription()); + $this->setAccess(isset($array['access']) ? $array['access'] : $this->getAccess()); + $this->setExpire(isset($array['expire']) ? $array['expire'] : $this->getExpire()); + $this->setAnonymous(isset($array['anonymous']) ? $array['anonymous'] : $this->getAnonymous()); + $this->setAllowMaybe(isset($array['allowMaybe']) ? $array['allowMaybe'] : $this->getAllowMaybe()); + $this->setVoteLimit(isset($array['voteLimit']) ? $array['voteLimit'] : $this->getVoteLimit()); + $this->setShowResults(isset($array['showResults']) ? $array['showResults'] : $this->getShowResults()); + $this->setDeleted(isset($array['deleted']) ? $array['deleted'] : $this->getDeleted()); + $this->setAdminAccess(isset($array['adminAccess']) ? $array['adminAccess'] : $this->getAdminAccess()); + return $this; + } + private function getDisplayName() { if (\OC::$server->getUserManager()->get($this->owner) instanceof IUser) { diff --git a/lib/Db/ShareMapper.php b/lib/Db/ShareMapper.php index 7de17583..3a4408f3 100644 --- a/lib/Db/ShareMapper.php +++ b/lib/Db/ShareMapper.php @@ -31,7 +31,7 @@ use OCP\AppFramework\Db\QBMapper; class ShareMapper extends QBMapper { /** - * CommentMapper constructor. + * ShareMapper constructor. * @param IDBConnection $db */ public function __construct(IDBConnection $db) { diff --git a/lib/Exceptions/EmptyTitleException.php b/lib/Exceptions/EmptyTitleException.php new file mode 100644 index 00000000..acfc4c57 --- /dev/null +++ b/lib/Exceptions/EmptyTitleException.php @@ -0,0 +1,40 @@ +<?php +/** + * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de> + * + * @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\Exceptions; + +use OCP\AppFramework\Http; + +class EmptyTitleException extends \Exception { + /** + * EmptyTitleException Constructor + * @param string $e exception message + */ + public function __construct($message = 'Poll title must not be empty') { + parent::__construct($message); + } + public function getStatus() { + return Http::STATUS_CONFLICT; + } + +} diff --git a/lib/Exceptions/InvalidAccessException.php b/lib/Exceptions/InvalidAccessException.php new file mode 100644 index 00000000..c5bfd69a --- /dev/null +++ b/lib/Exceptions/InvalidAccessException.php @@ -0,0 +1,40 @@ +<?php +/** + * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de> + * + * @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\Exceptions; + +use OCP\AppFramework\Http; + +class InvalidAccessException extends \Exception { + /** + * InvalidAccessException Constructor + * @param string $e exception message + */ + public function __construct($message = 'Invalid access value') { + parent::__construct($message); + } + public function getStatus() { + return Http::STATUS_CONFLICT; + } + +} diff --git a/lib/Exceptions/InvalidPollTypeException.php b/lib/Exceptions/InvalidPollTypeException.php new file mode 100644 index 00000000..bef690f3 --- /dev/null +++ b/lib/Exceptions/InvalidPollTypeException.php @@ -0,0 +1,40 @@ +<?php +/** + * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de> + * + * @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\Exceptions; + +use OCP\AppFramework\Http; + +class InvalidPollTypeException extends \Exception { + /** + * InvalidPollTypeException Constructor + * @param string $e exception message + */ + public function __construct($message = 'Invalid pollType value') { + parent::__construct($message); + } + public function getStatus() { + return Http::STATUS_CONFLICT; + } + +} diff --git a/lib/Exceptions/InvalidShowResultsException.php b/lib/Exceptions/InvalidShowResultsException.php new file mode 100644 index 00000000..67b18a49 --- /dev/null +++ b/lib/Exceptions/InvalidShowResultsException.php @@ -0,0 +1,40 @@ +<?php +/** + * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de> + * + * @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\Exceptions; + +use OCP\AppFramework\Http; + +class InvalidShowResultsException extends \Exception { + /** + * InvalidShowResultsException Constructor + * @param string $e exception message + */ + public function __construct($message = 'Invalid showResults value') { + parent::__construct($message); + } + public function getStatus() { + return Http::STATUS_CONFLICT; + } + +} diff --git a/lib/Exceptions/InvalidUsername.php b/lib/Exceptions/InvalidUsername.php new file mode 100644 index 00000000..b75c8ea0 --- /dev/null +++ b/lib/Exceptions/InvalidUsername.php @@ -0,0 +1,40 @@ +<?php +/** + * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de> + * + * @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\Exceptions; + +use OCP\AppFramework\Http; + +class InvalidUsername extends \Exception { + /** + * InvalidUsername Constructor + * @param string $e exception message + */ + public function __construct($e = 'Invalid username') { + parent::__construct($e); + } + public function getStatus() { + return Http::STATUS_CONFLICT; + } + +} diff --git a/lib/Exceptions/NotAuthorizedException.php b/lib/Exceptions/NotAuthorizedException.php new file mode 100644 index 00000000..9486790f --- /dev/null +++ b/lib/Exceptions/NotAuthorizedException.php @@ -0,0 +1,40 @@ +<?php +/** + * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de> + * + * @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\Exceptions; + +use OCP\AppFramework\Http; + +class NotAuthorizedException extends \Exception { + /** + * NotAuthorizedException Constructor + * @param string $e exception message + */ + public function __construct($e = 'Unauthorized') { + parent::__construct($e); + } + public function getStatus() { + return Http::STATUS_FORBIDDEN; + } + +} diff --git a/lib/Model/Acl.php b/lib/Model/Acl.php index 2c42980a..ebc998f2 100644 --- a/lib/Model/Acl.php +++ b/lib/Model/Acl.php @@ -136,6 +136,37 @@ class Acl implements JsonSerializable { } } + + /** + * @NoAdminRequired + * @return boolean + */ + public function setPollIdOrToken($pollId = 0, $token = '') { + + if ($token) { + $this->setToken($token); + } elseif ($pollId) { + $this->setPollId($pollId); + } + + return $this; + } + + /** + * @NoAdminRequired + * @return boolean + */ + public function checkAuthorize($pollId = 0, $token = '') { + + if ($token) { + $this->setToken($token); + } elseif ($pollId) { + $this->setPollId($pollId); + } + + return ($this->userId && $this->poll->getId()); + } + /** * @NoAdminRequired * @return string @@ -372,12 +403,14 @@ class Acl implements JsonSerializable { * @return string */ public function setToken(string $token): Acl { + $this->logger->debug('Share PollId' . $token); try { $this->token = $token; $share = $this->shareMapper->findByToken($token); $this->foundByToken = true; $this->setPollId($share->getPollId()); + $this->logger->debug('Share PollId' . $share->getPollId()); if (($share->getType() === 'group' || $share->getType() === 'user') && !\OC::$server->getUserSession()->isLoggedIn()) { // User must be logged in for shareType user and group 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/MailService.php b/lib/Service/MailService.php index e95f8784..915632f6 100644 --- a/lib/Service/MailService.php +++ b/lib/Service/MailService.php @@ -352,7 +352,7 @@ class MailService { foreach ($log as $logItem) { if ($logItem->getPollId() === $subscription->getPollId()) { - if ($poll->getAnonymous()) { + if ($poll->getAnonymous() || $poll->getShowResults() !== "always") { $displayUser = "A user"; } elseif ($this->userManager->get($logItem->getUserId()) instanceof IUser) { $displayUser = $this->userManager->get($logItem->getUserId())->getDisplayName(); 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); + } + +} |