diff --git a/appinfo/info.xml b/appinfo/info.xml index a809a0f95..ceba6c23b 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -28,6 +28,9 @@ OCA\Polls\Cron\NotificationCron + + OCA\Polls\Command\Share\Add + OCA\Polls\Migration\DeleteDuplicates diff --git a/lib/Command/Share/Add.php b/lib/Command/Share/Add.php new file mode 100644 index 000000000..9cce754f9 --- /dev/null +++ b/lib/Command/Share/Add.php @@ -0,0 +1,185 @@ + + * + * @author Daniel Rudolf + * + * @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 . + * + */ + +namespace OCA\Polls\Command\Share; + +use OC\Core\Command\Base; +use OCA\Polls\Db\Poll; +use OCA\Polls\Db\PollMapper; +use OCA\Polls\Exceptions\ShareAlreadyExistsException; +use OCA\Polls\Model\Email; +use OCA\Polls\Model\Group; +use OCA\Polls\Model\User; +use OCA\Polls\Service\ShareService; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserManager; +use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Add extends Base { + /** @var PollMapper */ + private $pollMapper; + + /** @var ShareService */ + private $shareService; + + /** @var IUserManager */ + private $userManager; + + /** @var IGroupManager */ + private $groupManager; + + public function __construct(PollMapper $pollMapper, + ShareService $shareService, + IUserManager $userManager, + IGroupManager $groupManager) { + parent::__construct(); + + $this->pollMapper = $pollMapper; + $this->shareService = $shareService; + $this->userManager = $userManager; + $this->groupManager = $groupManager; + } + + protected function configure(): void { + $this + ->setName('polls:share:add') + ->setDescription('Invites users to a poll') + ->addArgument( + 'id', + InputArgument::REQUIRED, + 'ID of the poll to invite users to' + )->addOption( + 'user', + null, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Invites the given users to the poll' + )->addOption( + 'group', + null, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Invites all members of the given groups to the poll' + )->addOption( + 'email', + null, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Sends invitation e-mails to the given addresses to participate in the poll' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $pollId = $input->getArgument('id'); + $users = $input->getOption('user'); + $groups = $input->getOption('group'); + $emails = $input->getOption('email'); + + try { + $poll = $this->pollMapper->find($pollId); + } catch (DoesNotExistException $e) { + $output->writeln('Poll not found.'); + return 1; + } + + $this->inviteUsers($poll, $users); + $this->inviteGroups($poll, $groups); + $this->inviteEmails($poll, $emails); + + $output->writeln('Users successfully invited to poll.'); + return 0; + } + + /** + * @param Poll $poll + * @param string[] $userIds + */ + private function inviteUsers(Poll $poll, array $userIds): void { + foreach ($userIds as $userId) { + try { + $share = $this->shareService->add($poll->getId(), User::TYPE, $userId); + $this->shareService->sendInvitation($share->getToken()); + } catch (ShareAlreadyExistsException $e) { + // silently ignore already existing shares + } + } + } + + /** + * @param Poll $poll + * @param string[] $groupIds + */ + private function inviteGroups(Poll $poll, array $groupIds): void { + foreach ($groupIds as $groupId) { + try { + $share = $this->shareService->add($poll->getId(), Group::TYPE, $groupId); + $this->shareService->sendInvitation($share->getToken()); + } catch (ShareAlreadyExistsException $e) { + // silently ignore already existing shares + } + } + } + + /** + * @param Poll $poll + * @param string[] $emails + */ + private function inviteEmails(Poll $poll, array $emails): void { + foreach ($emails as $email) { + try { + $share = $this->shareService->add($poll->getId(), Email::TYPE, $email); + $this->shareService->sendInvitation($share->getToken()); + } catch (ShareAlreadyExistsException $e) { + // silently ignore already existing shares + } + } + } + + public function completeOptionValues($optionName, CompletionContext $context) { + switch ($optionName) { + case 'user': + return $this->completeUserValues($context); + + case 'group': + return $this->completeGroupValues($context); + } + + return parent::completeOptionValues($optionName, $context); + } + + private function completeUserValues(CompletionContext $context): array { + return array_map(function (IUser $user) { + return $user->getUID(); + }, $this->userManager->search($context->getCurrentWord())); + } + + private function completeGroupValues(CompletionContext $context): array { + return array_map(function (IGroup $group) { + return $group->getGID(); + }, $this->groupManager->search($context->getCurrentWord())); + } +} diff --git a/lib/Model/Acl.php b/lib/Model/Acl.php index 20ce47110..fba39baef 100644 --- a/lib/Model/Acl.php +++ b/lib/Model/Acl.php @@ -252,10 +252,11 @@ class Acl implements JsonSerializable { /** * hasAdminAccess - Has user administrative rights? - * Returns true, if user is in admin group and poll has allowed admins to manage the poll + * Returns true, if user is in admin group and poll has allowed admins to manage the poll, + * or when running console commands. */ private function hasAdminAccess(): bool { - return ($this->getIsAdmin() && $this->poll->getAdminAccess()); + return (($this->getIsAdmin() && $this->poll->getAdminAccess()) || defined('OC_CONSOLE')); } /**