diff --git a/appinfo/routes.php b/appinfo/routes.php index 13b0e5ebb..aff2d7095 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -107,6 +107,7 @@ ['name' => 'Remote#test', 'url' => '/test', 'verb' => 'GET'], ['name' => 'Remote#event', 'url' => '/event/', 'verb' => 'POST'], ['name' => 'Remote#incoming', 'url' => '/incoming/', 'verb' => 'POST'], + ['name' => 'Remote#forward', 'url' => '/forward/', 'verb' => 'POST'], ['name' => 'Remote#circles', 'url' => '/circles/', 'verb' => 'GET'], ['name' => 'Remote#circle', 'url' => '/circle/{circleId}/', 'verb' => 'GET'], ['name' => 'Remote#members', 'url' => '/members/{circleId}/', 'verb' => 'GET'], diff --git a/lib/Command/CirclesCheck.php b/lib/Command/CirclesCheck.php index 890c210d4..774b37b3f 100644 --- a/lib/Command/CirclesCheck.php +++ b/lib/Command/CirclesCheck.php @@ -392,8 +392,10 @@ private function saveLoopback(InputInterface $input, OutputInterface $output, st [$scheme, $cloudId, $path] = $this->parseAddress($loopback); $question = new ConfirmationQuestion( - '- Do you want to save ' . $loopback - . ' as your loopback address ? (y/N) ', false, '/^(y|Y)/i' + '- Do you want to save ' + . $loopback + . ' as your loopback address ? (y/N) ', + false, '/^(y|Y)/i' ); $helper = $this->getHelper('question'); @@ -463,7 +465,8 @@ private function checkInternal(InputInterface $input, OutputInterface $output, s $fullInternal = rtrim($scheme . '://' . $cloudId . $path, '/'); $question = new ConfirmationQuestion( - 'Do you want to check the validity of this internal address? (Y/n) ', true, + 'Do you want to run a series of test to confirm the validity of this internal address? (Y/n) ', + true, '/^(y|Y)/i' ); @@ -573,8 +576,10 @@ private function saveInternal(InputInterface $input, OutputInterface $output, st $output->writeln(''); $question = new ConfirmationQuestion( - '- Do you want to save ' . $internal - . ' as your internal address ? (y/N) ', false, '/^(y|Y)/i' + '- Do you want to save ' + . $internal + . ' as your internal address ? (y/N) ', + false, '/^(y|Y)/i' ); $helper = $this->getHelper('question'); diff --git a/lib/Command/CirclesMaintenance.php b/lib/Command/CirclesMaintenance.php index bb2292974..e0572a37f 100644 --- a/lib/Command/CirclesMaintenance.php +++ b/lib/Command/CirclesMaintenance.php @@ -34,8 +34,11 @@ use OC\Core\Command\Base; use OCA\Circles\Db\CoreRequestBuilder; use OCA\Circles\Exceptions\MaintenanceException; +use OCA\Circles\Service\CircleService; +use OCA\Circles\Service\FederatedUserService; use OCA\Circles\Service\MaintenanceService; use OCA\Circles\Service\OutputService; +use OCA\Circles\Service\ShareService; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -104,6 +107,21 @@ protected function configure() { * @return int */ protected function execute(InputInterface $input, OutputInterface $output): int { + + + /** @var ShareService $shareService */ + $shareService = \OC::$server->get(ShareService::class); + /** @var CircleService $circleService */ + $circleService = \OC::$server->get(CircleService::class); + /** @var FederatedUserService $federatedUserService */ + $federatedUserService = \OC::$server->get(FederatedUserService::class); + $federatedUserService->setLocalCurrentUserId('test3A'); + + $circle = $circleService->getCircle('T3yPBiOeEn7Tv1KJ1BOkroECmaWEeuu'); + $shareService->syncRemoteShares($circle); + + + return 0; $reset = $input->getOption('reset'); $uninstall = $input->getOption('uninstall'); $level = (int)$input->getOption('level'); diff --git a/lib/Controller/RemoteController.php b/lib/Controller/RemoteController.php index a1cabb253..620c6b803 100644 --- a/lib/Controller/RemoteController.php +++ b/lib/Controller/RemoteController.php @@ -228,6 +228,32 @@ public function incoming(): DataResponse { } + /** + * @PublicPage + * @NoCSRFRequired + * + * @return DataResponse + */ + public function forward(): DataResponse { + try { + $event = $this->extractEventFromRequest(); + } catch (Exception $e) { + $this->e($e); + + return $this->exceptionResponse($e, Http::STATUS_UNAUTHORIZED); + } + + try { + $this->remoteDownstreamService->forwardedEvent($event); + + return new DataResponse($this->serialize($event->getResult())); + } catch (Exception $e) { + return $this->exceptionResponse($e); + } + } + + + /** * @PublicPage * @NoCSRFRequired diff --git a/lib/Cron/GlobalSync.php b/lib/Cron/GlobalSync.php index d1b55d56f..d8c756f12 100644 --- a/lib/Cron/GlobalSync.php +++ b/lib/Cron/GlobalSync.php @@ -50,7 +50,7 @@ class GlobalSync extends TimedJob { * Cache constructor. */ public function __construct() { - $this->setInterval(10); + $this->setInterval(900); } diff --git a/lib/Cron/Maintenance.php b/lib/Cron/Maintenance.php index 98588df40..4221b51cb 100644 --- a/lib/Cron/Maintenance.php +++ b/lib/Cron/Maintenance.php @@ -68,7 +68,7 @@ public function __construct( MaintenanceService $maintenanceService, ConfigService $configService ) { - $this->setInterval(10); + $this->setInterval(900); $this->maintenanceService = $maintenanceService; $this->configService = $configService; diff --git a/lib/FederatedItems/SharedItemsSync.php b/lib/FederatedItems/SharedFilesSync.php similarity index 59% rename from lib/FederatedItems/SharedItemsSync.php rename to lib/FederatedItems/SharedFilesSync.php index c69323a5e..48b650636 100644 --- a/lib/FederatedItems/SharedItemsSync.php +++ b/lib/FederatedItems/SharedFilesSync.php @@ -10,7 +10,7 @@ * later. See the COPYING file. * * @author Maxence Lange - * @copyright 2017 + * @copyright 2021 * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -32,30 +32,39 @@ namespace OCA\Circles\FederatedItems; use ArtificialOwl\MySmallPhpTools\Model\SimpleDataStore; +use OCA\Circles\Exceptions\RequestBuilderException; use OCA\Circles\IFederatedItem; +use OCA\Circles\IFederatedItemForwardResult; +use OCA\Circles\IFederatedItemHighSeverity; use OCA\Circles\IFederatedItemLimitedToInstanceWithMembership; use OCA\Circles\Model\Federated\FederatedEvent; -use OCA\Circles\Service\CircleEventService; +use OCA\Circles\Service\GlobalEventService; +use OCA\Circles\Service\ShareWrapperService; + /** - * Class SharesSync * - * @package OCA\Circles\FederatedItems */ -class SharedItemsSync implements +class SharedFilesSync implements IFederatedItem, + IFederatedItemForwardResult, + IFederatedItemHighSeverity, IFederatedItemLimitedToInstanceWithMembership { - // TODO: testing that IFederatedItemLimitedToInstanceWithMembership is working (since multi-instance) - // TODO: implements IFederatedItemInstanceMember to the check procedure + /** @var ShareWrapperService */ + private $shareWrapperService; - /** @var CircleEventService */ - private $circleEventService; + /** @var GlobalEventService */ + private $globalEventService; - public function __construct(CircleEventService $circleEventService) { - $this->circleEventService = $circleEventService; + public function __construct( + ShareWrapperService $shareWrapperService, + GlobalEventService $globalEventService + ) { + $this->shareWrapperService = $shareWrapperService; + $this->globalEventService = $globalEventService; } @@ -68,11 +77,16 @@ public function verify(FederatedEvent $event): void { /** * @param FederatedEvent $event + * + * @throws RequestBuilderException */ public function manage(FederatedEvent $event): void { - $this->circleEventService->onSharedItemsSyncRequested($event); + \OC::$server->getLogger()->log(3, '### MANAGE'); + $this->globalEventService->onSharedItemsSyncRequested($event); + $circle = $event->getCircle(); - $event->setResult(new SimpleDataStore(['shares' => 'ok'])); + $wrappedShares = $this->shareWrapperService->getSharesToCircle($circle->getSingleId()); + $event->setResult(new SimpleDataStore(['shares' => $wrappedShares])); } @@ -81,5 +95,6 @@ public function manage(FederatedEvent $event): void { * @param array $results */ public function result(FederatedEvent $event, array $results): void { + \OC::$server->getLogger()->log(3, '### RESULT: ' . json_encode($results)); } } diff --git a/lib/IFederatedItemForwardResult.php b/lib/IFederatedItemForwardResult.php new file mode 100644 index 000000000..1a6311663 --- /dev/null +++ b/lib/IFederatedItemForwardResult.php @@ -0,0 +1,40 @@ + + * @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; + +/** + * Interface IFederatedItemForwardResult + * + * @package OCA\Circles + */ +interface IFederatedItemForwardResult { +} diff --git a/lib/IFederatedItemLimitedToInstanceWithMembership.php b/lib/IFederatedItemLimitedToInstanceWithMembership.php index 00333aa57..d5b50df83 100644 --- a/lib/IFederatedItemLimitedToInstanceWithMembership.php +++ b/lib/IFederatedItemLimitedToInstanceWithMembership.php @@ -32,7 +32,7 @@ namespace OCA\Circles; /** - * Interface IFederatedItemInstanceMember + * Interface IFederatedItemLimitedToInstanceWithMembership * * @package OCA\Circles */ diff --git a/lib/Model/Federated/FederatedEvent.php b/lib/Model/Federated/FederatedEvent.php index 5dcaf6c53..a55453e0e 100644 --- a/lib/Model/Federated/FederatedEvent.php +++ b/lib/Model/Federated/FederatedEvent.php @@ -101,6 +101,9 @@ class FederatedEvent implements JsonSerializable { /** @var bool */ private $dataRequestOnly = false; + /** @var bool */ + private $forwardResult = false; + /** @var string */ private $sender = ''; @@ -222,6 +225,25 @@ public function setDataRequestOnly(bool $dataRequestOnly): self { } + /** + * @param bool $forwardResult + * + * @return FederatedEvent + */ + public function setForwardResult(bool $forwardResult): self { + $this->forwardResult = $forwardResult; + + return $this; + } + + /** + * @return bool + */ + public function isForwardResult(): bool { + return $this->forwardResult; + } + + /** * * Origin of the request diff --git a/lib/Model/Federated/RemoteInstance.php b/lib/Model/Federated/RemoteInstance.php index a3acd9a3a..41ec5a359 100644 --- a/lib/Model/Federated/RemoteInstance.php +++ b/lib/Model/Federated/RemoteInstance.php @@ -64,6 +64,7 @@ class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSeriali public const TEST = 'test'; public const ALIASES = 'aliases'; public const INCOMING = 'incoming'; + public const FORWARD = 'forward'; public const EVENT = 'event'; public const CIRCLES = 'circles'; public const CIRCLE = 'circle'; @@ -92,6 +93,9 @@ class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSeriali /** @var string */ private $incoming = ''; + /** @var string */ + private $forward = ''; + /** @var string */ private $root = ''; @@ -221,6 +225,25 @@ public function setIncoming(string $incoming): self { } + /** + * @param string $forward + * + * @return RemoteInstance + */ + public function setForward(string $forward): self { + $this->forward = $forward; + + return $this; + } + + /** + * @return string + */ + public function getForward(): string { + return $this->forward; + } + + /** * @return string */ @@ -486,6 +509,7 @@ public function import(array $data): NC22Signatory { ->setEvent($this->get(self::EVENT, $data)) ->setRoot($this->get(self::ROOT, $data)) ->setIncoming($this->get(self::INCOMING, $data)) + ->setForward($this->get(self::FORWARD, $data)) ->setCircles($this->get(self::CIRCLES, $data)) ->setCircle($this->get(self::CIRCLE, $data)) ->setMembers($this->get(self::MEMBERS, $data)) @@ -516,6 +540,7 @@ public function jsonSerialize(): array { self::ROOT => $this->getRoot(), self::EVENT => $this->getEvent(), self::INCOMING => $this->getIncoming(), + self::FORWARD => $this->getForward(), self::TEST => $this->getTest(), self::CIRCLES => $this->getCircles(), self::CIRCLE => $this->getCircle(), diff --git a/lib/Search/LocalUsers.php b/lib/Search/LocalUsers.php index 44dc2685b..8d3cc5a51 100644 --- a/lib/Search/LocalUsers.php +++ b/lib/Search/LocalUsers.php @@ -60,7 +60,7 @@ public function __construct(ICollaboratorSearch $search, ConfigService $configSe /** * {@inheritdoc} */ - public function search($search) { + public function search($search): array { $result = []; $userManager = \OC::$server->getUserManager(); @@ -86,7 +86,8 @@ public function search($search) { * @return array */ private function searchFromCollaborator($search): array { - [$temp, $hasMore] = $this->search->search($search, [IShare::TYPE_USER, IShare::TYPE_EMAIL], false, 50, 0); + [$temp, $hasMore] = + $this->search->search($search, [IShare::TYPE_USER, IShare::TYPE_EMAIL], false, 50, 0); $result = array_merge($temp['exact']['users'], $temp['users']); $parsed = []; diff --git a/lib/Service/FederatedEventService.php b/lib/Service/FederatedEventService.php index f94983ab1..41c1b6f75 100644 --- a/lib/Service/FederatedEventService.php +++ b/lib/Service/FederatedEventService.php @@ -56,6 +56,7 @@ use OCA\Circles\IFederatedItemAsyncProcess; use OCA\Circles\IFederatedItemCircleCheckNotRequired; use OCA\Circles\IFederatedItemDataRequestOnly; +use OCA\Circles\IFederatedItemForwardResult; use OCA\Circles\IFederatedItemHighSeverity; use OCA\Circles\IFederatedItemInitiatorCheckNotRequired; use OCA\Circles\IFederatedItemInitiatorMembershipNotRequired; @@ -194,6 +195,30 @@ public function newEvent(FederatedEvent $event): array { } + /** + * @param FederatedEvent $event + * + * @return bool + * @throws RequestNetworkException + */ + public function forwardEvent(FederatedEvent $event): bool { + if (!$event->isForwardResult() || $this->configService->isLocalInstance($event->getOrigin())) { + return false; + } + + $remote = $this->remoteRequest->getFromInstance($event->getOrigin()); + $request = new NC22Request('', Request::TYPE_POST); + $this->configService->configureRequest($request); + $request->basedOnUrl($remote->getForward()); + $request->setDataSerialize($event); + + + $this->doRequest($request); + + return true; + } + + /** * This confirmation is optional, method is just here to avoid going too far away on the process * @@ -377,6 +402,9 @@ private function configureEvent(FederatedEvent $event, IFederatedItem $item) { if ($item instanceof IFederatedItemDataRequestOnly) { $event->setDataRequestOnly(true); } + if ($item instanceof IFederatedItemForwardResult) { + $event->setForwardResult(true); + } } @@ -510,7 +538,9 @@ public function manageResults(string $token): void { try { $gs = $this->getFederatedItem($event, false); - $gs->result($event, $results); + if (!$this->forwardEvent($event)) { + $gs->result($event, $results); + } } catch (FederatedEventException $e) { } } diff --git a/lib/Service/GlobalEventService.php b/lib/Service/GlobalEventService.php new file mode 100644 index 000000000..7bbf2e555 --- /dev/null +++ b/lib/Service/GlobalEventService.php @@ -0,0 +1,88 @@ + + * + * @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\Service; + +use ArtificialOwl\MySmallPhpTools\Model\SimpleDataStore; +use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger; +use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc23\TNC23Logger; +use OCA\Circles\AppInfo\Application; +use OCA\Circles\Events\AddingCircleMemberEvent; +use OCA\Circles\Events\CircleCreatedEvent; +use OCA\Circles\Events\CircleDestroyedEvent; +use OCA\Circles\Events\CircleEditedEvent; +use OCA\Circles\Events\CircleGenericEvent; +use OCA\Circles\Events\CircleMemberAddedEvent; +use OCA\Circles\Events\CircleMemberEditedEvent; +use OCA\Circles\Events\CircleMemberRemovedEvent; +use OCA\Circles\Events\CircleMemberRequestedEvent; +use OCA\Circles\Events\CreatingCircleEvent; +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; +use OCA\Circles\Events\RequestingCircleMemberEvent; +use OCA\Circles\Model\Federated\FederatedEvent; +use OCA\Circles\Model\Membership; +use OCA\Circles\Model\Mount; +use OCA\Circles\Model\ShareWrapper; +use OCP\EventDispatcher\IEventDispatcher; + +class GlobalEventService { + use TNC23Logger; + + + /** @var IEventDispatcher */ + private $eventDispatcher; + + + /** + * EventService constructor. + * + * @param IEventDispatcher $eventDispatcher + */ + public function __construct() { + $this->setup('app', Application::APP_ID); + } + + + /** + * @param FederatedEvent $federatedEvent + */ + public function onSharedItemsSyncRequested(FederatedEvent $federatedEvent) { + + } +} diff --git a/lib/Service/MaintenanceService.php b/lib/Service/MaintenanceService.php index 57ba6b37d..68fa8a00a 100644 --- a/lib/Service/MaintenanceService.php +++ b/lib/Service/MaintenanceService.php @@ -225,6 +225,12 @@ private function runMaintenance3(): void { $this->eventWrapperService->retry(EventWrapperService::RETRY_HOURLY); } catch (Exception $e) { } + + try { +// $this->output('broadcast shares'); +// $this->globalSyncService('') + } catch (Exception $e) { + } } diff --git a/lib/Service/RemoteDownstreamService.php b/lib/Service/RemoteDownstreamService.php index 8b6d19e35..d4b038d69 100644 --- a/lib/Service/RemoteDownstreamService.php +++ b/lib/Service/RemoteDownstreamService.php @@ -188,6 +188,25 @@ public function incomingEvent(FederatedEvent $event): void { } + + /** + * @param FederatedEvent $event + */ + public function forwardedEvent(FederatedEvent $event): void { + try { + $gs = $this->federatedEventService->getFederatedItem($event, false); + $this->confirmOriginEvent($event); + $this->confirmContent($event, false); + + $gs->result($event, $event->getResult()->gAll()); + } catch (Exception $e) { + $this->e($e, ['event' => $event]); + } + } + + + + /** * @param FederatedEvent $event * @param bool $full diff --git a/lib/Service/RemoteStreamService.php b/lib/Service/RemoteStreamService.php index 1ebe3dbfb..76e5291e6 100644 --- a/lib/Service/RemoteStreamService.php +++ b/lib/Service/RemoteStreamService.php @@ -140,6 +140,7 @@ public function getAppSignatory(bool $generate = true, string $confirmKey = ''): $app->setRoot($this->interfaceService->getCloudPath()); $app->setEvent($this->interfaceService->getCloudPath('circles.Remote.event')); $app->setIncoming($this->interfaceService->getCloudPath('circles.Remote.incoming')); + $app->setForward($this->interfaceService->getCloudPath('circles.Remote.forward')); $app->setTest($this->interfaceService->getCloudPath('circles.Remote.test')); $app->setCircles($this->interfaceService->getCloudPath('circles.Remote.circles')); $app->setCircle( diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php index 1235fd62c..0a20d5620 100644 --- a/lib/Service/ShareService.php +++ b/lib/Service/ShareService.php @@ -31,6 +31,7 @@ namespace OCA\Circles\Service; +use OCA\Circles\FederatedItems\SharedFilesSync; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Federated\FederatedEvent; @@ -65,8 +66,8 @@ public function __construct(FederatedEventService $federatedEventService, Config * @param Circle $circle */ public function syncRemoteShares(Circle $circle) { -// $event = new FederatedEvent(SharedItemsSync::class); -// $event->setCircle($circle); -// $this->federatedEventService->newEvent($event); + $event = new FederatedEvent(SharedFilesSync::class); + $event->setCircle($circle); + $this->federatedEventService->newEvent($event); } }