Skip to content

Commit

Permalink
Merge pull request #3039 from nextcloud/enh/send-all-invitations
Browse files Browse the repository at this point in the history
send all invitations
  • Loading branch information
dartcafe authored Aug 31, 2023
2 parents 31ff2da + b9b1ef0 commit 0ae22e2
Show file tree
Hide file tree
Showing 20 changed files with 352 additions and 169 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
## [5.3.0] - tbd
### New
- Add label to public shares
- Send all unsent invitations to a poll with one click (resolves contact groups and circles too)
### Fixes
- Fix API calls
### Changes
Expand Down
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@

['name' => 'share#list', 'url' => '/poll/{pollId}/shares', 'verb' => 'GET'],
['name' => 'share#add', 'url' => '/poll/{pollId}/share', 'verb' => 'POST'],
['name' => 'share#send_all_invitations', 'url' => '/poll/{pollId}/inviteAll', 'verb' => 'PUT'],
['name' => 'share#delete', 'url' => '/share/{token}', 'verb' => 'DELETE'],
['name' => 'share#personal', 'url' => '/share/personal', 'verb' => 'POST'],
['name' => 'share#sendInvitation', 'url' => '/share/{token}/invite', 'verb' => 'POST'],
Expand Down
6 changes: 3 additions & 3 deletions lib/Command/Share/Add.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ 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());
$this->shareService->sendInvitation($share);
} catch (ShareAlreadyExistsException $e) {
// silently ignore already existing shares
}
Expand All @@ -110,7 +110,7 @@ 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());
$this->shareService->sendInvitation($share);
} catch (ShareAlreadyExistsException $e) {
// silently ignore already existing shares
}
Expand All @@ -125,7 +125,7 @@ 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());
$this->shareService->sendInvitation($share);
} catch (ShareAlreadyExistsException $e) {
// silently ignore already existing shares
}
Expand Down
6 changes: 3 additions & 3 deletions lib/Command/Share/Remove.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
private function removeUsers(Poll $poll, array $userIds): void {
foreach ($this->getUserShares($poll) as $share) {
if (in_array($share->getUserId(), $userIds, true)) {
$this->shareService->delete($share->getToken());
$this->shareService->delete($share);
}
}
}
Expand All @@ -107,7 +107,7 @@ private function removeUsers(Poll $poll, array $userIds): void {
private function removeGroups(Poll $poll, array $groupIds): void {
foreach ($this->getGroupShares($poll) as $share) {
if (in_array($share->getUserId(), $groupIds, true)) {
$this->shareService->delete($share->getToken());
$this->shareService->delete($share);
}
}
}
Expand All @@ -119,7 +119,7 @@ private function removeGroups(Poll $poll, array $groupIds): void {
private function removeEmails(Poll $poll, array $emails): void {
foreach ($this->getEmailShares($poll) as $share) {
if (in_array($share->getEmailAddress(), $emails, true)) {
$this->shareService->delete($share->getToken());
$this->shareService->delete($share);
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions lib/Controller/PublicController.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,10 @@ public function deleteEmailAddress(string $token): JSONResponse {
* @PublicPage
*/
public function register(string $token, string $userName, string $emailAddress = '', string $timeZone = ''): JSONResponse {
$publicShare = $this->shareService->get($token);
$personalShare = $this->shareService->register($publicShare, $userName, $emailAddress, $timeZone);
return $this->responseCreate(fn () => [
'share' => $this->shareService->register($this->shareService->get($token), $userName, $emailAddress, $timeZone)
'share' => $personalShare,
], $token);
}

Expand All @@ -310,8 +312,10 @@ public function register(string $token, string $userName, string $emailAddress =
* @PublicPage
*/
public function resendInvitation(string $token): JSONResponse {
$share = $this->shareService->get($token);
return $this->response(fn () => [
'share' => $this->mailService->resendInvitation($token)
'share' => $share,
'sentResult' => $this->mailService->sendInvitation($share)
], $token);
}
}
5 changes: 2 additions & 3 deletions lib/Controller/ShareApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function add(int $pollId, string $type, string $userId = ''): JSONRespons
* @NoCSRFRequired
*/
public function delete(string $token): JSONResponse {
return $this->responseDeleteTolerant(fn () => ['share' => $this->shareService->delete($token)]);
return $this->responseDeleteTolerant(fn () => ['share' => $this->shareService->delete(token: $token)]);
}

/**
Expand All @@ -85,11 +85,10 @@ public function delete(string $token): JSONResponse {
* @NoCSRFRequired
*/
public function sendInvitation(string $token): JSONResponse {
$sentResult = $this->mailService->sendInvitation($token);
$share = $this->shareService->get($token);
return $this->response(fn () => [
'share' => $share,
'sentResult' => $sentResult
'sentResult' => $this->mailService->sendInvitation($share),
]);
}
}
50 changes: 20 additions & 30 deletions lib/Controller/ShareController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
namespace OCA\Polls\Controller;

use OCA\Polls\Db\Share;
use OCA\Polls\Exceptions\InvalidShareTypeException;
use OCA\Polls\Exceptions\ShareAlreadyExistsException;
use OCA\Polls\Service\ShareService;
use OCA\Polls\Service\UserService;
use OCP\AppFramework\Http\JSONResponse;
Expand Down Expand Up @@ -112,18 +110,31 @@ public function setEmailAddress(string $token, string $emailAddress = ''): JSONR
*/

public function delete(string $token): JSONResponse {
return $this->responseDeleteTolerant(fn () => ['share' => $this->shareService->delete($token)]);
return $this->responseDeleteTolerant(fn () => ['share' => $this->shareService->delete(token: $token)]);
}

/**
* Sent invitation mails for a share
* Send invitation mails for a share
* Additionally send notification via notifications
* @NoAdminRequired
*/
public function sendInvitation(string $token): JSONResponse {
$share = $this->shareService->get($token);
return $this->response(fn () => [
'share' => $this->shareService->get($token),
'sentResult' => $this->shareService->sendInvitation($token),
'share' => $share,
'sentResult' => $this->shareService->sendInvitation($share),
]);
}

/**
* Send all invitation mails for a share and resolve groups
* Additionally send notification via notifications
* @NoAdminRequired
*/
public function sendAllInvitations(int $pollId): JSONResponse {
return $this->response(fn () => [
'poll' => $pollId,
'sentResult' => $this->shareService->sendAllInvitations($pollId),
]);
}

Expand All @@ -132,29 +143,8 @@ public function sendInvitation(string $token): JSONResponse {
* @NoAdminRequired
*/
public function resolveGroup(string $token): JSONResponse {
return $this->response(function () use ($token) {
$shares = [];
$share = $this->shareService->get($token);
$resolvableShares = [
Share::TYPE_CIRCLE,
Share::TYPE_CONTACTGROUP
];

if (!in_array($share->getType(), $resolvableShares)) {
throw new InvalidShareTypeException('Cannot resolve members from share type ' . $share->getType());
}

foreach ($this->userService->getUser($share->getType(), $share->getUserId())->getMembers() as $member) {
try {
$newShare = $this->shareService->add($share->getPollId(), $member->getType(), $member->getId());
$shares[] = $newShare;
} catch (ShareAlreadyExistsException $e) {
continue;
}
}

$this->shareService->delete($token);
return ['shares' => $shares];
});
return $this->response(fn () => [
'shares' => $this->shareService->resolveGroup($token)
]);
}
}
4 changes: 4 additions & 0 deletions lib/Db/Share.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ class Share extends Entity implements JsonSerializable {
self::TYPE_CIRCLE,
self::TYPE_CONTACTGROUP,
];
public const RESOLVABLE_SHARES = [
self::TYPE_CIRCLE,
self::TYPE_CONTACTGROUP
];

public $id = null;
protected IURLGenerator $urlGenerator;
Expand Down
17 changes: 17 additions & 0 deletions lib/Db/ShareMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,23 @@ public function findByPoll(int $pollId): array {

return $this->findEntities($qb);
}
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
* @return Share[]
* @psalm-return array<array-key, Share>
*/
public function findByPollNotInvited(int $pollId): array {
$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('invitation_sent', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));

return $this->findEntities($qb);
}
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
* @return Share[]
Expand Down
56 changes: 56 additions & 0 deletions lib/Model/SentResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?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\Model;

class SentResult implements \JsonSerializable {
public const INVALID_EMAIL_ADDRESS = 'InvalidMail';
public const UNHANDELED_REASON = 'UnknownError';

private array $sentMails = [];
private array $abortedMails = [];

public function AddSentMail(UserBase $user): void {
array_push($this->sentMails, [
'emailAddress' => $user->getEmailAddress(),
'displayName' => $user->getDisplayName(),
]);
}

public function AddAbortedMail(UserBase $user, string $reason = self::UNHANDELED_REASON): void {
array_push($this->abortedMails, [
'emailAddress' => $user->getEmailAddress(),
'displayName' => $user->getDisplayName(),
'reason' => $reason,
]);
}

public function jsonSerialize(): array {
return [
'sentMails' => $this->sentMails,
'abortedMails' => $this->abortedMails,
'countSentMails' => count($this->sentMails),
'countAbortedMails' => count($this->abortedMails),
];
}
}
Loading

0 comments on commit 0ae22e2

Please sign in to comment.