Signed-off-by: dartcafe <github@dartcafe.de>
This commit is contained in:
dartcafe 2022-06-27 19:37:21 +02:00
Родитель f254e9c33f
Коммит 3904d95446
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CCE73CEF3035D3C8
11 изменённых файлов: 208 добавлений и 3 удалений

Просмотреть файл

@ -39,6 +39,7 @@
<command>OCA\Polls\Command\Share\Add</command>
<command>OCA\Polls\Command\Share\Remove</command>
<command>OCA\Polls\Command\Db\Rebuild</command>
<command>OCA\Polls\Command\Poll\TransferOwnership</command>
</commands>
<settings>
<admin-section>OCA\Polls\Settings\AdminSection</admin-section>

Просмотреть файл

@ -67,6 +67,8 @@ return [
['name' => 'poll#clone', 'url' => '/poll/{pollId}/clone', 'verb' => 'GET'],
['name' => 'poll#getParticipantsEmailAddresses', 'url' => '/poll/{pollId}/addresses', 'verb' => 'GET'],
['name' => 'poll#transfer_polls', 'url' => '/polls/transfer/{sourceUser}/{destinationUser}', 'verb' => 'PUT'],
['name' => 'option#list', 'url' => '/poll/{pollId}/options', 'verb' => 'GET'],
['name' => 'option#add', 'url' => '/option', 'verb' => 'POST'],
['name' => 'option#addBulk', 'url' => '/option/bulk', 'verb' => 'POST'],
@ -118,6 +120,7 @@ return [
// REST-API calls
['name' => 'poll_api#list', 'url' => '/api/v1.0/polls', 'verb' => 'GET'],
['name' => 'poll_api#transfer_polls', 'url' => '/api/v1.0/polls/transfer/{sourceUser}/{destinationUser}', 'verb' => 'PUT'],
['name' => 'poll_api#add', 'url' => '/api/v1.0/poll', 'verb' => 'POST'],
['name' => 'poll_api#get', 'url' => '/api/v1.0/poll/{pollId}', 'verb' => 'GET'],
['name' => 'poll_api#update', 'url' => '/api/v1.0/poll/{pollId}', 'verb' => 'PUT'],

Просмотреть файл

@ -47,6 +47,7 @@ use OCA\Polls\Event\PollArchivedEvent;
use OCA\Polls\Event\PollCreatedEvent;
use OCA\Polls\Event\PollDeletedEvent;
use OCA\Polls\Event\PollExpiredEvent;
use OCA\Polls\Event\PollOwnerChangeEvent;
use OCA\Polls\Event\PollRestoredEvent;
use OCA\Polls\Event\PollTakeoverEvent;
use OCA\Polls\Event\PollUpdatedEvent;
@ -98,6 +99,7 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(PollDeletedEvent::class, PollListener::class);
$context->registerEventListener(PollExpiredEvent::class, PollListener::class);
$context->registerEventListener(PollRestoredEvent::class, PollListener::class);
$context->registerEventListener(PollOwnerChangeEvent::class, PollListener::class);
$context->registerEventListener(PollTakeoverEvent::class, PollListener::class);
$context->registerEventListener(PollUpdatedEvent::class, PollListener::class);
$context->registerEventListener(ShareChangedEmailEvent::class, ShareListener::class);

Просмотреть файл

@ -0,0 +1,110 @@
<?php
/**
* @copyright Copyright (c) 2021 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\Command\Poll;
use OCA\Polls\Service\PollService;
use OCP\IUser;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
class TransferOwnership extends Command {
/** @var PollService */
private $pollService;
/** @var IUserManager */
private $userManager;
public function __construct(
IUserManager $userManager,
PollService $pollService
) {
parent::__construct();
$this->pollService = $pollService;
$this->userManager = $userManager;
}
protected function configure(): void {
$this
->setName('polls:poll:transfer-ownership')
->setDescription('Transfer the ownership of one user\'s polls to another user.')
->addArgument(
'source-user',
InputArgument::REQUIRED,
'User id to transfer the polls from'
)
->addArgument(
'target-user',
InputArgument::REQUIRED,
'User id to transfer the polls to'
);
}
protected function execute(InputInterface $input, OutputInterface $output): int {
if ($this->requestConfirmation($input, $output)) {
return 1;
}
if (!$this->userManager->get($input->getArgument('target-user')) instanceof IUser) {
$output->writeln('<error> Unknown destination user ' . $input->getArgument('target-user') . '</error>');
return 1;
}
$transferredPolls = $this->pollService->transferPolls($input->getArgument('source-user'), $input->getArgument('target-user'));
if (sizeof($transferredPolls) < 1) {
$output->writeln('<info>No polls were transferred from ' . $input->getArgument('source-user') . '</info>');
} else if (sizeof($transferredPolls) === 1) {
$output->writeln('<info>One poll was transferred from ' . $input->getArgument('source-user') . ' to ' . $input->getArgument('target-user') . '</info>');
$output->writeln('<info> * ' . $transferredPolls[0]->getId() . ' - ' . $transferredPolls[0]->getTitle() . '</info>');
} else {
$output->writeln('<info>' . sizeof($transferredPolls) . ' polls were transferred from ' . $input->getArgument('source-user') . ' to ' . $input->getArgument('target-user') . '</info>');
foreach ($transferredPolls as $poll) {
$output->writeln('<info> * ' . $poll->getId() . ' - ' . $poll->getTitle() . '</info>');
}
}
return 0;
}
private function requestConfirmation(InputInterface $input, OutputInterface $output): int {
if ($input->isInteractive()) {
$helper = $this->getHelper('question');
$output->writeln('<comment>This command will change the ownership of all polls of ' . $input->getArgument('source-user') . ' to ' . $input->getArgument('target-user') . '.</comment>');
$output->writeln('<comment>NO notifications will be sent to the users.</comment>');
$output->writeln('');
$question = new ConfirmationQuestion('Continue with the transfer (y/n)? [n] ', false);
if (!$helper->ask($input, $output, $question)) {
return 1;
}
}
return 0;
}
}

Просмотреть файл

@ -168,6 +168,19 @@ class PollApiController extends ApiController {
}
}
/**
* Clone poll
* @CORS
* @NoCSRFRequired
*/
public function transferPolls(string $sourceUser, string $targetUser): JSONResponse {
try {
return new JSONResponse(['transferred' => $this->pollService->transferPolls($sourceUser, $targetUser)], Http::STATUS_CREATED);
} catch (Exception $e) {
return new JSONResponse(['message' => $e->getMessage()], $e->getStatus());
}
}
/**
* Collect email addresses from particitipants
* @NoAdminRequired

Просмотреть файл

@ -138,6 +138,13 @@ class PollController extends Controller {
return $this->get($pollId);
}
/**
* Transfer polls between users
*/
public function transferPolls(string $sourceUser, string $targetUser): JSONResponse {
return $this->response(fn () => $this->pollService->transferPolls($sourceUser, $targetUser));
}
/**
* Collect email addresses from particitipants
* @NoAdminRequired

Просмотреть файл

@ -94,6 +94,18 @@ class PollMapper extends QBMapper {
return $this->findEntities($qb);
}
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
* @return Poll[]
*/
public function findOwner(string $userId): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
return $this->findEntities($qb);
}
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
* @return Poll[]

Просмотреть файл

@ -0,0 +1,35 @@
<?php
/*
* @copyright Copyright (c) 2021 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\Event;
use OCA\Polls\Db\Poll;
class PollOwnerChangeEvent extends PollEvent {
public function __construct(
Poll $poll
) {
parent::__construct($poll);
$this->activitySubject = self::OWNER_CHANGE;
}
}

Просмотреть файл

@ -26,12 +26,11 @@ namespace OCA\Polls\Event;
use OCA\Polls\Notification\Notifier;
use OCA\Polls\Db\Poll;
class PollTakeoverEvent extends PollEvent {
class PollTakeoverEvent extends PollOwnerChangeEvent {
public function __construct(
Poll $poll
) {
parent::__construct($poll);
$this->activitySubject = self::OWNER_CHANGE;
}
public function getNotification(): array {

Просмотреть файл

@ -80,6 +80,7 @@ abstract class BaseListener implements IEventListener {
public function handle(Event $event) : void {
$this->event = $event;
try {
$this->checkClass();
$this->addLog();
@ -111,7 +112,6 @@ abstract class BaseListener implements IEventListener {
throw $e;
}
}
// add a cron job, if necessary (i.e. for removed users and groups)
$this->addCronJob();

Просмотреть файл

@ -41,11 +41,15 @@ use OCA\Polls\Db\Vote;
use OCA\Polls\Event\PollArchivedEvent;
use OCA\Polls\Event\PollCreatedEvent;
use OCA\Polls\Event\PollDeletedEvent;
use OCA\Polls\Event\PollOwnerChangeEvent;
use OCA\Polls\Event\PollRestoredEvent;
use OCA\Polls\Event\PollTakeoverEvent;
use OCA\Polls\Event\PollUpdatedEvent;
use OCA\Polls\Exceptions\InvalidUsernameException;
use OCA\Polls\Model\Acl;
use OCA\Polls\Model\Settings\AppSettings;
use OCP\IUser;
use OCP\IUserManager;
class PollService {
@ -54,6 +58,9 @@ class PollService {
/** @var IEventDispatcher */
private $eventDispatcher;
/** @var IUserManager */
private $userManager;
/** @var IUserSession */
private $userSession;
@ -87,6 +94,7 @@ class PollService {
AppSettings $appSettings,
IEventDispatcher $eventDispatcher,
IGroupManager $groupManager,
IUserManager $userManager,
IUserSession $userSession,
MailService $mailService,
Poll $poll,
@ -103,6 +111,7 @@ class PollService {
$this->poll = $poll;
$this->pollMapper = $pollMapper;
$this->userId = $UserId;
$this->userManager = $userManager;
$this->userSession = $userSession;
$this->voteMapper = $voteMapper;
$this->vote = $vote;
@ -191,6 +200,20 @@ class PollService {
return $this->poll;
}
public function transferPolls(string $sourceUser, string $targetUser) {
if ($this->userManager->get($targetUser) instanceof IUser) {
$pollsToTransfer = $this->pollMapper->findOwner($sourceUser);
foreach ($pollsToTransfer as $poll) {
$poll->setOwner($targetUser);
$this->pollMapper->update($poll);
$this->eventDispatcher->dispatchTyped(new PollOwnerChangeEvent($poll));
}
return $pollsToTransfer;
}
throw new InvalidUsernameException('The user id "' . $targetUser . '" is not valid.');
}
/**
* get poll configuration
*/