diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 0cd87502a..190262c63 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -38,6 +38,8 @@ use OC; use OCA\Circles\Events\AddingCircleMemberEvent; use OCA\Circles\Events\CircleMemberAddedEvent; +use OCA\Circles\Events\Files\CreatingFileShareEvent; +use OCA\Circles\Events\Files\FileShareCreatedEvent; use OCA\Circles\Events\MembershipsCreatedEvent; use OCA\Circles\Events\MembershipsRemovedEvent; use OCA\Circles\Events\RemovingCircleMemberEvent; @@ -48,9 +50,11 @@ use OCA\Circles\Listeners\Examples\ExampleMembershipsCreated; use OCA\Circles\Listeners\Examples\ExampleMembershipsRemoved; use OCA\Circles\Listeners\Examples\ExampleRequestingCircleMember; -use OCA\Circles\Listeners\Files\AddingMember as ListenerFilesAddingMember; -use OCA\Circles\Listeners\Files\MemberAdded as ListenerFilesMemberAdded; +use OCA\Circles\Listeners\Files\AddingMemberSendMail as ListenerFilesAddingMemberSendMail; +use OCA\Circles\Listeners\Files\CreatingShareSendMail as ListenerFilesCreatingShareSendMail; +use OCA\Circles\Listeners\Files\MemberAddedSendMail as ListenerFilesMemberAddedSendMail; use OCA\Circles\Listeners\Files\RemovingMember as ListenerFilesRemovingMember; +use OCA\Circles\Listeners\Files\ShareCreatedSendMail as ListenerFilesShareCreatedSendMail; use OCA\Circles\Listeners\GroupCreated; use OCA\Circles\Listeners\GroupDeleted; use OCA\Circles\Listeners\GroupMemberAdded; @@ -137,11 +141,26 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(UserRemovedEvent::class, GroupMemberRemoved::class); // Local Events (for Files/Shares/Notifications management) - $context->registerEventListener(AddingCircleMemberEvent::class, ListenerFilesAddingMember::class); - $context->registerEventListener(CircleMemberAddedEvent::class, ListenerFilesMemberAdded::class); + $context->registerEventListener( + AddingCircleMemberEvent::class, + ListenerFilesAddingMemberSendMail::class + ); + $context->registerEventListener( + CircleMemberAddedEvent::class, + ListenerFilesMemberAddedSendMail::class + ); + $context->registerEventListener( + CreatingFileShareEvent::class, + ListenerFilesCreatingShareSendMail::class + ); + $context->registerEventListener( + FileShareCreatedEvent::class, + ListenerFilesShareCreatedSendMail::class + ); $context->registerEventListener(RemovingCircleMemberEvent::class, ListenerFilesRemovingMember::class); $context->registerEventListener( - RequestingCircleMemberEvent::class, ListenerNotificationsRequestingMember::class + RequestingCircleMemberEvent::class, + ListenerNotificationsRequestingMember::class ); // It seems that AccountManager use deprecated dispatcher, let's use a deprecated listener diff --git a/lib/Events/Files/CreatingFileShareEvent.php b/lib/Events/Files/CreatingFileShareEvent.php new file mode 100644 index 000000000..2e5a991ff --- /dev/null +++ b/lib/Events/Files/CreatingFileShareEvent.php @@ -0,0 +1,81 @@ + + * @copyright 2021 + * @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\Circles\Events\Files; + +use OCA\Circles\Events\CircleGenericEvent; +use OCA\Circles\Model\Federated\FederatedEvent; +use OCA\Circles\Model\Mount; + +/** + * Class CreatingFileShareEvent + * + * @package OCA\Circles\Events\Files + */ +class CreatingFileShareEvent extends CircleGenericEvent { + + + /** @var Mount */ + private $mount; + + + /** + * CreatingFileShareEvent constructor. + * + * @param FederatedEvent $federatedEvent + */ + public function __construct(FederatedEvent $federatedEvent) { + parent::__construct($federatedEvent); + } + + + /** + * @param Mount $mount + */ + public function setMount(Mount $mount): void { + $this->mount = $mount; + } + + /** + * @return Mount + */ + public function getMount(): Mount { + return $this->mount; + } + + /** + * @return bool + */ + public function hasMount(): bool { + return !is_null($this->mount); + } +} diff --git a/lib/Events/Files/FileShareCreatedEvent.php b/lib/Events/Files/FileShareCreatedEvent.php new file mode 100644 index 000000000..df056c7d9 --- /dev/null +++ b/lib/Events/Files/FileShareCreatedEvent.php @@ -0,0 +1,55 @@ + + * @copyright 2021 + * @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\Circles\Events\Files; + +use ArtificialOwl\MySmallPhpTools\Model\SimpleDataStore; +use OCA\Circles\Events\CircleResultGenericEvent; +use OCA\Circles\Model\Federated\FederatedEvent; + +/** + * Class CreatingFileShareEvent + * + * @package OCA\Circles\Events\Files + */ +class FileShareCreatedEvent extends CircleResultGenericEvent { + + + /** + * FileShareCreatedEvent constructor. + * + * @param FederatedEvent $federatedEvent + * @param SimpleDataStore[] $result + */ + public function __construct(FederatedEvent $federatedEvent, array $result) { + parent::__construct($federatedEvent, $result); + } +} diff --git a/lib/FederatedItems/Files/FileShare.php b/lib/FederatedItems/Files/FileShare.php index b9a4d5b01..5e534bb81 100644 --- a/lib/FederatedItems/Files/FileShare.php +++ b/lib/FederatedItems/Files/FileShare.php @@ -75,6 +75,7 @@ class FileShare implements * FileShare constructor. * * @param MountRequest $mountRequest + * @param EventService $eventService * @param ConfigService $configService */ public function __construct( @@ -105,18 +106,23 @@ public function verify(FederatedEvent $event): void { * @throws CircleNotFoundException */ public function manage(FederatedEvent $event): void { - if ($this->configService->isLocalInstance($event->getOrigin())) { - return; + $mount = null; + if (!$this->configService->isLocalInstance($event->getOrigin())) { + /** @var ShareWrapper $wrappedShare */ + $wrappedShare = $event->getParams()->gObj('wrappedShare', ShareWrapper::class); + $mount = new Mount(); + $mount->fromShare($wrappedShare); + $mount->setMountId($this->token(15)); + + $this->mountRequest->save($mount); } - /** @var ShareWrapper $wrappedShare */ - $wrappedShare = $event->getParams()->gObj('wrappedShare', ShareWrapper::class); - $mount = new Mount(); - $mount->fromShare($wrappedShare); - $mount->setMountId($this->token(15)); + $this->eventService->fileShareCreating($event, $mount); - $this->mountRequest->save($mount); - $this->eventService->federatedShareCreated($wrappedShare, $mount); +// $this->eventService->federatedShareCreated($wrappedShare, $mount); + + +// $this->eventService->fileSharing($event); // $this->mountRequest->create($mount); // $circle = $event->getDeprecatedCircle(); @@ -172,6 +178,8 @@ public function manage(FederatedEvent $event): void { * @param array $results */ public function result(FederatedEvent $event, array $results): void { + $this->eventService->fileShareCreated($event, $results); + // $event = null; // $contacts = []; // foreach (array_keys($events) as $instance) { diff --git a/lib/Listeners/Files/AddingMember.php b/lib/Listeners/Files/AddingMemberSendMail.php similarity index 85% rename from lib/Listeners/Files/AddingMember.php rename to lib/Listeners/Files/AddingMemberSendMail.php index 13c0ebf53..f31cd9f1f 100644 --- a/lib/Listeners/Files/AddingMember.php +++ b/lib/Listeners/Files/AddingMemberSendMail.php @@ -37,7 +37,6 @@ use OCA\Circles\AppInfo\Application; use OCA\Circles\Events\AddingCircleMemberEvent; use OCA\Circles\Exceptions\RequestBuilderException; -use OCA\Circles\Exceptions\ShareTokenAlreadyExistException; use OCA\Circles\Model\Member; use OCA\Circles\Service\ConfigService; use OCA\Circles\Service\ContactService; @@ -51,7 +50,7 @@ * * @package OCA\Circles\Listeners\Files */ -class AddingMember implements IEventListener { +class AddingMemberSendMail implements IEventListener { use TStringTools; use TNC22Logger; @@ -126,7 +125,7 @@ public function handle(Event $event): void { foreach ($shares as $share) { try { $shareToken = $this->shareTokenService->generateShareToken($share, $member); - } catch (ShareTokenAlreadyExistException $e) { + } catch (Exception $e) { continue; } @@ -136,29 +135,10 @@ public function handle(Event $event): void { $result[$member->getId()] = [ 'shares' => $files, - 'mails' => $this->getMailAddressesFromContact($member) + 'mails' => $this->contactService->getMailAddressesFromMember($member) ]; } $event->getFederatedEvent()->setResultEntry('files', $result); } - - - /** - * @param Member $member - * - * @return array - */ - private function getMailAddressesFromContact(Member $member): array { - if ($member->getUserType() !== Member::TYPE_CONTACT - || !$this->configService->isLocalInstance($member->getInstance())) { - return []; - } - - try { - return $this->contactService->getMailAddresses($member->getUserId()); - } catch (Exception $e) { - return []; - } - } } diff --git a/lib/Listeners/Files/CreatingShareSendMail.php b/lib/Listeners/Files/CreatingShareSendMail.php new file mode 100644 index 000000000..18e7e00e3 --- /dev/null +++ b/lib/Listeners/Files/CreatingShareSendMail.php @@ -0,0 +1,138 @@ + + * @copyright 2021 + * @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\Circles\Listeners\Files; + +use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger; +use ArtificialOwl\MySmallPhpTools\Traits\TStringTools; +use Exception; +use OCA\Circles\AppInfo\Application; +use OCA\Circles\Events\Files\CreatingFileShareEvent; +use OCA\Circles\Exceptions\ShareWrapperNotFoundException; +use OCA\Circles\Model\Member; +use OCA\Circles\Model\ShareWrapper; +use OCA\Circles\Service\ConfigService; +use OCA\Circles\Service\ContactService; +use OCA\Circles\Service\ShareTokenService; +use OCA\Circles\Service\ShareWrapperService; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +/** + * Class CreatingShareSendMail + * + * @package OCA\Circles\Listeners\Files + */ +class CreatingShareSendMail implements IEventListener { + use TStringTools; + use TNC22Logger; + + + /** @var ShareWrapperService */ + private $shareWrapperService; + + /** @var ShareTokenService */ + private $shareTokenService; + + /** @var ConfigService */ + private $configService; + + /** @var ContactService */ + private $contactService; + + + /** + * CreatingShareSendMail constructor. + * + * @param ShareWrapperService $shareWrapperService + * @param ShareTokenService $shareTokenService + * @param ContactService $contactService + * @param ConfigService $configService + */ + public function __construct( + ShareWrapperService $shareWrapperService, + ShareTokenService $shareTokenService, + ContactService $contactService, + ConfigService $configService + ) { + $this->shareWrapperService = $shareWrapperService; + $this->shareTokenService = $shareTokenService; + $this->contactService = $contactService; + $this->configService = $configService; + + $this->setup('app', Application::APP_ID); + } + + + /** + * @param Event $event + */ + public function handle(Event $event): void { + if (!$event instanceof CreatingFileShareEvent) { + return; + } + + $circle = $event->getCircle(); + $federatedEvent = $event->getFederatedEvent(); + + $result = []; + foreach ($circle->getInheritedMembers() as $member) { + if ($member->getUserType() !== Member::TYPE_MAIL + && $member->getUserType() !== Member::TYPE_CONTACT) { + continue; + } + + $share = null; + if ($this->configService->isLocalInstance($federatedEvent->getOrigin())) { + try { + /** @var ShareWrapper $share */ + $share = $federatedEvent->getParams()->gObj('wrappedShare', ShareWrapper::class); + $this->shareWrapperService->getShareById((int)$share->getId()); + // we confirm share is not spoofed by the main instance of the Circle + if ($share->getSharedWith() !== $circle->getSingleId()) { + throw new ShareWrapperNotFoundException(); + } + $shareToken = $this->shareTokenService->generateShareToken($share, $member); + $share->setShareToken($shareToken); + } catch (Exception $e) { + $share = null; + } + } + + $result[$member->getId()] = [ + 'share' => $share, + 'mails' => $this->contactService->getMailAddressesFromMember($member) + ]; + } + + $event->getFederatedEvent()->setResultEntry('shares', $result); + } +} diff --git a/lib/Listeners/Files/MemberAddedSendMail.php b/lib/Listeners/Files/MemberAddedSendMail.php new file mode 100644 index 000000000..7dc00d594 --- /dev/null +++ b/lib/Listeners/Files/MemberAddedSendMail.php @@ -0,0 +1,126 @@ + + * @copyright 2021 + * @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\Circles\Listeners\Files; + +use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger; +use ArtificialOwl\MySmallPhpTools\Traits\TStringTools; +use OCA\Circles\AppInfo\Application; +use OCA\Circles\Events\CircleMemberAddedEvent; +use OCA\Circles\Model\Member; +use OCA\Circles\Model\ShareWrapper; +use OCA\Circles\Service\SendMailService; +use OCA\Circles\Service\ShareWrapperService; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +/** + * Class MemberAdded + * + * @package OCA\Circles\Listeners\Files + */ +class MemberAddedSendMail implements IEventListener { + use TStringTools; + use TNC22Logger; + + + /** @var ShareWrapperService */ + private $shareWrapperService; + + /** @var SendMailService */ + private $sendMailService; + + + /** + * MemberAdded constructor. + * + * @param ShareWrapperService $shareWrapperService + * @param SendMailService $sendMailService + */ + public function __construct( + ShareWrapperService $shareWrapperService, + SendMailService $sendMailService + ) { + $this->sendMailService = $sendMailService; + $this->shareWrapperService = $shareWrapperService; + + $this->setup('app', Application::APP_ID); + } + + + /** + * @param Event $event + */ + public function handle(Event $event): void { + if (!$event instanceof CircleMemberAddedEvent) { + return; + } + + $member = $event->getMember(); + $circle = $event->getCircle(); + + if ($member->getUserType() === Member::TYPE_CIRCLE) { + $members = $member->getBasedOn()->getInheritedMembers(); + } else { + $members = [$member]; + } + + /** @var Member[] $members */ + foreach ($members as $member) { + if ($member->getUserType() !== Member::TYPE_MAIL + && $member->getUserType() !== Member::TYPE_CONTACT + ) { + continue; + } + + $mails = []; + $shares = []; + foreach ($event->getResults() as $origin => $item) { + $files = $item->gData('files'); + if (!$files->hasKey($member->getId())) { + continue; + } + + $data = $files->gData($member->getId()); + $shares = array_merge($shares, $data->gObjs('shares', ShareWrapper::class)); + + // TODO: is it safe to use $origin to compare getInstance() ? + // TODO: do we need to check the $origin ? + // TODO: Solution would be to check the origin based on aliases using RemoteInstanceService +// if ($member->getUserType() === Member::TYPE_CONTACT && $member->getInstance() === $origin) { + $mails = $data->gArray('mails'); +// } + } + + $this->sendMailService->generateMail($circle, $member, $shares, $mails); + } + } +} diff --git a/lib/Listeners/Files/ShareCreatedSendMail.php b/lib/Listeners/Files/ShareCreatedSendMail.php new file mode 100644 index 000000000..17e1f21d5 --- /dev/null +++ b/lib/Listeners/Files/ShareCreatedSendMail.php @@ -0,0 +1,145 @@ + + * @copyright 2021 + * @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\Circles\Listeners\Files; + +use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger; +use ArtificialOwl\MySmallPhpTools\Traits\TStringTools; +use Exception; +use OCA\Circles\AppInfo\Application; +use OCA\Circles\Events\Files\FileShareCreatedEvent; +use OCA\Circles\Model\Member; +use OCA\Circles\Model\ShareWrapper; +use OCA\Circles\Service\ConfigService; +use OCA\Circles\Service\ContactService; +use OCA\Circles\Service\SendMailService; +use OCA\Circles\Service\ShareTokenService; +use OCA\Circles\Service\ShareWrapperService; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +/** + * Class ShareCreatedSendMail + * + * @package OCA\Circles\Listeners\Files + */ +class ShareCreatedSendMail implements IEventListener { + use TStringTools; + use TNC22Logger; + + + /** @var ShareWrapperService */ + private $shareWrapperService; + + /** @var ShareTokenService */ + private $shareTokenService; + + /** @var SendMailService */ + private $sendMailService; + + /** @var ConfigService */ + private $configService; + + /** @var ContactService */ + private $contactService; + + + /** + * ShareCreatedSendMail constructor. + * + * @param ShareWrapperService $shareWrapperService + * @param ShareTokenService $shareTokenService + * @param SendMailService $sendMailService + * @param ContactService $contactService + * @param ConfigService $configService + */ + public function __construct( + ShareWrapperService $shareWrapperService, + ShareTokenService $shareTokenService, + SendMailService $sendMailService, + ContactService $contactService, + ConfigService $configService + ) { + $this->shareWrapperService = $shareWrapperService; + $this->shareTokenService = $shareTokenService; + $this->sendMailService = $sendMailService; + $this->contactService = $contactService; + $this->configService = $configService; + + $this->setup('app', Application::APP_ID); + } + + + /** + * @param Event $event + */ + public function handle(Event $event): void { + if (!$event instanceof FileShareCreatedEvent) { + return; + } + + $circle = $event->getCircle(); + + foreach ($circle->getInheritedMembers() as $member) { + if ($member->getUserType() !== Member::TYPE_MAIL + && $member->getUserType() !== Member::TYPE_CONTACT) { + continue; + } + + $mails = []; + $share = null; + foreach ($event->getResults() as $origin => $item) { + $shares = $item->gData('shares'); + if (!$shares->hasKey($member->getId())) { + continue; + } + + $data = $shares->gData($member->getId()); + $mails = array_merge($mails, $data->gArray('mails')); + + // TODO: is it safe to use $origin to compare getInstance() ? + // TODO: do we need to check the $origin ? + // TODO: Solution would be to check the origin based on aliases using RemoteInstanceService +// if ($member->getUserType() === Member::TYPE_CONTACT && $member->getInstance() === $origin) { + try { + $share = $data->gObj('share', ShareWrapper::class); + } catch (Exception $e) { + } + +// } + } + + if (!is_null($share)) { + $this->sendMailService->generateMail($circle, $member, [$share], $mails); + } + } + } +} diff --git a/lib/Model/ShareWrapper.php b/lib/Model/ShareWrapper.php index 8fd8d3f91..6f207c7fa 100644 --- a/lib/Model/ShareWrapper.php +++ b/lib/Model/ShareWrapper.php @@ -728,7 +728,7 @@ public function import(array $data): IDeserializable { ->setItemTarget($this->get('itemTarget', $data)) ->setFileSource($this->getInt('fileSource', $data)) ->setFileTarget($this->get('fileTarget', $data)) - ->setSharedWith($this->get('shareWith', $data)) + ->setSharedWith($this->get('sharedWith', $data)) ->setSharedBy($this->get('uidInitiator', $data)) ->setShareOwner($this->get('uidOwner', $data)) ->setToken($this->get('token', $data)) diff --git a/lib/Service/ContactService.php b/lib/Service/ContactService.php index 110c47e6f..9f63623c7 100644 --- a/lib/Service/ContactService.php +++ b/lib/Service/ContactService.php @@ -34,10 +34,12 @@ use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger; use ArtificialOwl\MySmallPhpTools\Traits\TArrayTools; use ArtificialOwl\MySmallPhpTools\Traits\TStringTools; +use Exception; use OC; use OCA\Circles\Exceptions\ContactAddressBookNotFoundException; use OCA\Circles\Exceptions\ContactFormatException; use OCA\Circles\Exceptions\ContactNotFoundException; +use OCA\Circles\Model\Member; use OCA\DAV\CardDAV\ContactsManager; use OCP\Contacts\IManager; use OCP\IAddressBook; @@ -187,4 +189,23 @@ public function getAddressBoxById(IManager $cm, string $addressBookKey): IAddres throw new ContactAddressBookNotFoundException(); } + + + /** + * @param Member $member + * + * @return array + */ + public function getMailAddressesFromMember(Member $member): array { + if ($member->getUserType() !== Member::TYPE_CONTACT + || !$this->configService->isLocalInstance($member->getInstance())) { + return []; + } + + try { + return $this->getMailAddresses($member->getUserId()); + } catch (Exception $e) { + return []; + } + } } diff --git a/lib/Service/EventService.php b/lib/Service/EventService.php index d63ab0a00..ba507de21 100644 --- a/lib/Service/EventService.php +++ b/lib/Service/EventService.php @@ -50,6 +50,8 @@ use OCA\Circles\Events\DestroyingCircleEvent; use OCA\Circles\Events\EditingCircleEvent; use OCA\Circles\Events\EditingCircleMemberEvent; +use OCA\Circles\Events\Files\CreatingFileShareEvent; +use OCA\Circles\Events\Files\FileShareCreatedEvent; use OCA\Circles\Events\MembershipsCreatedEvent; use OCA\Circles\Events\MembershipsRemovedEvent; use OCA\Circles\Events\RemovingCircleMemberEvent; @@ -303,6 +305,29 @@ public function memberLeft(FederatedEvent $federatedEvent, array $results): void } + /** + * @param FederatedEvent $federatedEvent + * @param Mount|null $mount + */ + public function fileShareCreating(FederatedEvent $federatedEvent, ?Mount $mount = null): void { + $event = new CreatingFileShareEvent($federatedEvent); + if (!is_null($mount)) { + $event->setMount($mount); + } + $this->eventDispatcher->dispatchTyped($event); + } + + + /** + * @param FederatedEvent $federatedEvent + * @param SimpleDataStore[] $result + */ + public function fileShareCreated(FederatedEvent $federatedEvent, array $result): void { + $event = new FileShareCreatedEvent($federatedEvent, $result); + $this->eventDispatcher->dispatchTyped($event); + } + + /** * @param Membership[] $new */ diff --git a/lib/Service/RemoteDownstreamService.php b/lib/Service/RemoteDownstreamService.php index 6c40b55dd..8b6d19e35 100644 --- a/lib/Service/RemoteDownstreamService.php +++ b/lib/Service/RemoteDownstreamService.php @@ -152,13 +152,13 @@ public function requestedEvent(FederatedEvent $event): void { } $event->setOrigin($event->getSender()); - $event->resetData() - ->resetResult(); + $event->resetData(); $this->federatedEventService->confirmInitiator($event, false); $this->confirmContent($event, true); $item->verify($event); + $event->resetResult(); if ($event->isDataRequestOnly()) { return; diff --git a/lib/Listeners/Files/MemberAdded.php b/lib/Service/SendMailService.php similarity index 62% rename from lib/Listeners/Files/MemberAdded.php rename to lib/Service/SendMailService.php index 4e6a9687a..ea3bd32a1 100644 --- a/lib/Listeners/Files/MemberAdded.php +++ b/lib/Service/SendMailService.php @@ -29,34 +29,24 @@ */ -namespace OCA\Circles\Listeners\Files; +namespace OCA\Circles\Service; -use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger; -use ArtificialOwl\MySmallPhpTools\Traits\TStringTools; use Exception; -use OCA\Circles\AppInfo\Application; -use OCA\Circles\Events\CircleMemberAddedEvent; -use OCA\Circles\Exceptions\RequestBuilderException; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Member; use OCA\Circles\Model\ShareWrapper; -use OCA\Circles\Service\ShareWrapperService; use OCP\Defaults; -use OCP\EventDispatcher\Event; -use OCP\EventDispatcher\IEventListener; use OCP\IL10N; use OCP\Mail\IEMailTemplate; use OCP\Mail\IMailer; use OCP\Util; /** - * Class MemberAdded + * Class SendMailService * - * @package OCA\Circles\Listeners\Files + * @package OCA\Circles\Service */ -class MemberAdded implements IEventListener { - use TStringTools; - use TNC22Logger; +class SendMailService { /** @var IL10N */ @@ -68,79 +58,22 @@ class MemberAdded implements IEventListener { /** @var Defaults */ private $defaults; - /** @var ShareWrapperService */ - private $shareWrapperService; - /** - * MemberAdded constructor. + * SendMailService constructor. * * @param IL10N $l10n * @param IMailer $mailer * @param Defaults $defaults - * @param ShareWrapperService $shareWrapperService */ public function __construct( IL10N $l10n, IMailer $mailer, - Defaults $defaults, - ShareWrapperService $shareWrapperService + Defaults $defaults ) { $this->l10n = $l10n; $this->mailer = $mailer; $this->defaults = $defaults; - $this->shareWrapperService = $shareWrapperService; - - $this->setup('app', Application::APP_ID); - } - - - /** - * @param Event $event - * - * @throws RequestBuilderException - */ - public function handle(Event $event): void { - if (!$event instanceof CircleMemberAddedEvent) { - return; - } - - $member = $event->getMember(); - $circle = $event->getCircle(); - - if ($member->getUserType() === Member::TYPE_CIRCLE) { - $members = $member->getBasedOn()->getInheritedMembers(); - } else { - $members = [$member]; - } - - /** @var Member[] $members */ - foreach ($members as $member) { - if ($member->getUserType() !== Member::TYPE_MAIL - && $member->getUserType() !== Member::TYPE_CONTACT - ) { - continue; - } - - $mails = []; - $shares = []; - foreach ($event->getResults() as $origin => $item) { - $files = $item->gData('files'); - if (!$files->hasKey($member->getId())) { - continue; - } - - $data = $files->gData($member->getId()); - $shares = array_merge($shares, $data->gObjs('shares', ShareWrapper::class)); - - // TODO: is it safe to use $origin to compare getInstance() ? - if ($member->getUserType() === Member::TYPE_CONTACT && $member->getInstance() === $origin) { - $mails = $data->gArray('mails'); - } - } - - $this->generateMail($circle, $member, $shares, $mails); - } } @@ -150,7 +83,7 @@ public function handle(Event $event): void { * @param ShareWrapper[] $shares * @param array $mails */ - private function generateMail(Circle $circle, Member $member, array $shares, array $mails): void { + public function generateMail(Circle $circle, Member $member, array $shares, array $mails): void { if (empty($shares)) { return; } @@ -181,7 +114,7 @@ private function generateMail(Circle $circle, Member $member, array $shares, arr $this->fillMailExistingShares($template, $links); foreach ($mails as $mail) { try { - $this->sendMailExistingShares($template, $invitedBy, $mail); + $this->sendMailExistingShares($template, $invitedBy, $mail, sizeof($links) > 1); } catch (Exception $e) { } } @@ -221,15 +154,21 @@ private function fillMailExistingShares(IEMailTemplate $emailTemplate, array $li * @param IEMailTemplate $emailTemplate * @param string $author * @param string $recipient + * @param bool $multiple * * @throws Exception */ private function sendMailExistingShares( IEMailTemplate $emailTemplate, string $author, - string $recipient + string $recipient, + bool $multiple = false ) { - $subject = $this->l10n->t('%s shared multiple files with you.', [$author]); + if ($multiple) { + $subject = $this->l10n->t('%s shared multiple files with you.', [$author]); + } else { + $subject = $this->l10n->t('%s shared a file with you.', [$author]); + } $instanceName = $this->defaults->getName(); $senderName = $this->l10n->t('%s on %s', [$author, $instanceName]); diff --git a/lib/Service/ShareTokenService.php b/lib/Service/ShareTokenService.php index 98edee6bc..399c19b66 100644 --- a/lib/Service/ShareTokenService.php +++ b/lib/Service/ShareTokenService.php @@ -79,12 +79,18 @@ public function __construct( * * @return ShareToken * @throws ShareTokenAlreadyExistException + * @throws ShareTokenNotFoundException */ public function generateShareToken( ShareWrapper $share, Member $member, string $password = '' ): ShareToken { + if ($member->getUserType() !== Member::TYPE_MAIL + && $member->getUserType() !== Member::TYPE_CONTACT) { + throw new ShareTokenNotFoundException(); + } + $token = $this->token(19); $shareToken = new ShareToken();