%PDF- %PDF-
| Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/circles/lib/Service/ |
| Current File : /www/varak.net/nextcloud.varak.net/apps_old/apps/circles/lib/Service/RemoteDownstreamService.php |
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Circles\Service;
use Exception;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteInstanceException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Probes\CircleProbe;
use OCA\Circles\Tools\Exceptions\InvalidItemException;
use OCA\Circles\Tools\Exceptions\RequestNetworkException;
use OCA\Circles\Tools\Exceptions\SignatoryException;
use OCA\Circles\Tools\Traits\TAsync;
use OCA\Circles\Tools\Traits\TNCLogger;
/**
* Class RemoteDownstreamService
*
* @package OCA\Circles\Service
*/
class RemoteDownstreamService {
use TNCLogger;
use TAsync;
/** @var CircleRequest */
private $circleRequest;
/** @var MemberRequest */
private $memberRequest;
/** @var FederatedEventService */
private $federatedEventService;
/** @var RemoteService */
private $remoteService;
/** @var ConfigService */
private $configService;
/**
* RemoteDownstreamService constructor.
*
* @param CircleRequest $circleRequest
* @param MemberRequest $memberRequest
* @param FederatedEventService $federatedEventService
* @param ConfigService $configService
*/
public function __construct(
CircleRequest $circleRequest,
MemberRequest $memberRequest,
FederatedEventService $federatedEventService,
RemoteService $remoteService,
ConfigService $configService
) {
$this->setup('app', 'circles');
$this->circleRequest = $circleRequest;
$this->memberRequest = $memberRequest;
$this->federatedEventService = $federatedEventService;
$this->remoteService = $remoteService;
$this->configService = $configService;
}
//
//
// /**
// * @param GSEvent $event
// *
// * @throws CircleDoesNotExistException
// * @throws ConfigNoCircleAvailableException
// * @throws GSKeyException
// * @throws GlobalScaleDSyncException
// * @throws GlobalScaleEventException
// */
// public function statusEvent(GSEvent $event) {
// $this->globalScaleService->checkEvent($event);
//
// $gs = $this->globalScaleService->getGlobalScaleEvent($event);
// $gs->verify($event, false);
// $gs->manage($event);
// }
//
/**
* @param FederatedEvent $event
*
* @throws FederatedEventDSyncException
* @throws FederatedEventException
* @throws InitiatorNotConfirmedException
* @throws OwnerNotFoundException
* @throws FederatedItemException
* @throws RequestBuilderException
*/
public function requestedEvent(FederatedEvent $event): void {
$item = $this->federatedEventService->getFederatedItem($event, true);
if (!$this->configService->isLocalInstance($event->getCircle()->getInstance())) {
throw new FederatedEventDSyncException('Circle is not from this instance');
}
if ($event->isLimitedToInstanceWithMember()) {
$instances = $this->memberRequest->getMemberInstances($event->getCircle()->getSingleId());
if (!in_array($event->getSender(), $instances)) {
throw new FederatedEventException('Instance have no members in this Circle');
}
}
$event->setOrigin($event->getSender());
$event->resetData();
$this->federatedEventService->confirmInitiator($event, false);
$this->confirmContent($event, true);
$item->verify($event);
$event->resetResult();
if ($event->isDataRequestOnly()) {
return;
}
if (!$event->isAsync()) {
$item->manage($event);
}
$this->federatedEventService->initBroadcast($event);
}
/**
* @param FederatedEvent $event
*/
public function incomingEvent(FederatedEvent $event): void {
try {
$gs = $this->federatedEventService->getFederatedItem($event, false);
$this->confirmOriginEvent($event);
$this->confirmContent($event, false);
$gs->manage($event);
} catch (Exception $e) {
$this->e($e, ['event' => $event->getWrapperToken()]);
}
}
/**
* @param FederatedEvent $event
* @param bool $full
*
* @throws FederatedEventDSyncException
* @throws OwnerNotFoundException
*/
private function confirmContent(FederatedEvent $event, bool $full = true): void {
$this->confirmCircle($event);
$this->confirmMember($event, $full);
}
/**
* @param FederatedEvent $event
*
* @throws CircleNotFoundException
* @throws FederatedEventDSyncException
* @throws InvalidIdException
* @throws InvalidItemException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestBuilderException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
*/
private function confirmCircle(FederatedEvent $event): void {
if ($event->canBypass(FederatedEvent::BYPASS_LOCALCIRCLECHECK) || $this->verifyCircle($event)) {
return;
}
throw new FederatedEventDSyncException('Could not verify Circle');
}
/**
* @param FederatedEvent $event
*
* @return bool
* @throws CircleNotFoundException
* @throws OwnerNotFoundException
* @throws RequestBuilderException
* @throws InvalidIdException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws UnknownRemoteException
* @throws InvalidItemException
* @throws RequestNetworkException
* @throws SignatoryException
*/
private function verifyCircle(FederatedEvent $event): bool {
$circle = $event->getCircle();
try {
$probe = new CircleProbe();
$probe->includeSystemCircles()
->includePersonalCircles();
$localCircle = $this->circleRequest->getCircle($circle->getSingleId(), null, $probe);
} catch (CircleNotFoundException $e) {
try {
$this->remoteService->syncRemoteCircle(
$circle->getSingleId(),
$circle->getOwner()->getInstance()
);
return true;
} catch (Exception $e) {
return false;
}
}
if (!$localCircle->compareWith($circle)) {
$this->debug(
'failed to compare Circles',
['localCircle' => json_encode($localCircle), 'circle' => json_encode($circle)]
);
return false;
}
return true;
}
/**
* @param FederatedEvent $event
* @param bool $full
* // TODO: Check IFederatedItemMember*
*
* @throws FederatedEventDSyncException
*/
private function confirmMember(FederatedEvent $event, bool $full): void {
if ($event->canBypass(FederatedEvent::BYPASS_LOCALMEMBERCHECK) || !$event->hasMember()
|| $this->verifyMember($event, $full)) {
return;
}
throw new FederatedEventDSyncException('Could not verify Member');
}
/**
* @param FederatedEvent $event
* @param bool $full
*
* @return bool
*/
private function verifyMember(FederatedEvent $event, bool $full): bool {
$this->debug('verifyMember()', ['event' => $event]);
$member = $event->getMember();
try {
$localMember = $this->memberRequest->getMemberById($member->getId());
} catch (MemberNotFoundException $e) {
$this->debug('Member not found', ['member' => $member]);
return false;
}
if (!$localMember->compareWith($member, $full)) {
$this->debug(
'failed to compare Members',
['localMember' => json_encode($localMember), 'member' => json_encode($member)]
);
return false;
}
return true;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedEventException
* @throws OwnerNotFoundException
*/
private function confirmOriginEvent(FederatedEvent $event): void {
if ($event->getSender() !== $event->getCircle()->getInstance()) {
$this->debug('invalid origin', ['event' => $event]);
throw new FederatedEventException('invalid origin');
}
}
}