more migration

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
This commit is contained in:
Maxence Lange 2021-02-03 12:54:43 -01:00
parent c6abf3216b
commit 4162791f5d
48 changed files with 1627 additions and 1078 deletions

14
TODO.md
View file

@ -20,8 +20,8 @@ I got lazy and afraid to get lost the first throw of code
- [ ] #M003: confirm other type of User when adding a new member to a circle.
- [ ] confirm MemberId and CircleId is really not known before creating entry in database.
- Add better option to circles:manage:list
- [x] Add better option to circles:manage:list
- [ ] when generating Single circle, update single_id with the generated id in the table circle_members
### Ideas
@ -36,12 +36,12 @@ Should I do it ?
### renaming
Some Model/Method needs renaming for better readability
- [ ] rename getViewer/setViewer to getInitiator/setInitiator
- [ ] rename IMember to ICircleUser
- [x] rename getViewer/setViewer to getInitiator/setInitiator
- [x] rename IMember to IFederatedUser
- [ ] rename Member to CircleMember
- [ ] rename CurrentUser to CloudUser
- [ ] rename IRemoteEvent to IRemoteItem or IRemoteCommand or IRemoteObject
- [ ] rename RemoteEvent (needed ?)
- [x] rename CurrentUser to FederatedUser
- [x] rename IRemoteEvent to IFederatedItem, IFederatedCommand, IFederatedAction, IFederatedObject
- [x] rename RemoteEvent to FederatedEvent

View file

@ -32,11 +32,12 @@ namespace OCA\Circles\Command;
use OC\Core\Command\Base;
use OC\User\NoUserException;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteEventException;
use OCA\Circles\Exceptions\ViewerNotFoundException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\CurrentUserService;
use OCA\Circles\Service\FederatedUserService;
use OCP\IL10N;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputArgument;
@ -58,8 +59,8 @@ class CirclesCreate extends Base {
/** @var IUserManager */
private $userManager;
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/** @var CircleService */
private $circleService;
@ -70,17 +71,17 @@ class CirclesCreate extends Base {
*
* @param IL10N $l10n
* @param IUserManager $userManager
* @param CurrentUserService $currentUserService
* @param FederatedUserService $federatedUserService
* @param CircleService $circleService
*/
public function __construct(
IL10N $l10n, IUserManager $userManager, CurrentUserService $currentUserService,
IL10N $l10n, IUserManager $userManager, FederatedUserService $federatedUserService,
CircleService $circleService
) {
parent::__construct();
$this->l10n = $l10n;
$this->userManager = $userManager;
$this->currentUserService = $currentUserService;
$this->federatedUserService = $federatedUserService;
$this->circleService = $circleService;
}
@ -102,17 +103,18 @@ class CirclesCreate extends Base {
* @return int
* @throws CircleNotFoundException
* @throws NoUserException
* @throws RemoteEventException
* @throws ViewerNotFoundException
* @throws FederatedEventException
* @throws InitiatorNotFoundException
* @throws OwnerNotFoundException
* @throws InitiatorNotConfirmedException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$ownerId = $input->getArgument('owner');
$name = $input->getArgument('name');
$this->currentUserService->bypassCurrentUserCondition(true);
$this->federatedUserService->bypassCurrentUserCondition(true);
$owner = $this->currentUserService->createLocalCurrentUser($ownerId);
$owner = $this->federatedUserService->createLocalFederatedUser($ownerId);
$circle = $this->circleService->create($name, $owner);
echo json_encode($circle, JSON_PRETTY_PRINT) . "\n";

View file

@ -39,16 +39,17 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
use OC\Core\Command\Base;
use OC\User\NoUserException;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Exceptions\ViewerNotFoundException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\ModelManager;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\CurrentUserService;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\RemoteService;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
@ -72,8 +73,8 @@ class CirclesList extends Base {
/** @var ModelManager */
private $modelManager;
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/** @var CircleService */
private $circleService;
@ -89,18 +90,18 @@ class CirclesList extends Base {
* CirclesList constructor.
*
* @param ModelManager $modelManager
* @param CurrentUserService $currentUserService
* @param FederatedUserService $federatedUserService
* @param CircleService $circleService
* @param RemoteService $remoteService
* @param ConfigService $configService
*/
public function __construct(
ModelManager $modelManager, CurrentUserService $currentUserService, CircleService $circleService,
ModelManager $modelManager, FederatedUserService $federatedUserService, CircleService $circleService,
RemoteService $remoteService, ConfigService $configService
) {
parent::__construct();
$this->modelManager = $modelManager;
$this->currentUserService = $currentUserService;
$this->federatedUserService = $federatedUserService;
$this->circleService = $circleService;
$this->remoteService = $remoteService;
$this->configService = $configService;
@ -115,7 +116,7 @@ class CirclesList extends Base {
->addOption('member', '', InputOption::VALUE_REQUIRED, 'search for member', '')
->addOption('def', '', InputOption::VALUE_NONE, 'display complete circle configuration')
->addOption('all', '', InputOption::VALUE_NONE, 'display also hidden Circles')
->addOption('viewer', '', InputOption::VALUE_REQUIRED, 'set viewer', '')
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
->addOption('json', '', InputOption::VALUE_NONE, 'returns result as JSON');
}
@ -134,22 +135,22 @@ class CirclesList extends Base {
* @throws SignatoryException
* @throws SignatureException
* @throws UnknownRemoteException
* @throws ViewerNotFoundException
* @throws InitiatorNotFoundException
* @throws OwnerNotFoundException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$member = $input->getOption('member');
$viewer = $input->getOption('viewer');
$json = $input->getOption('json');
$remote = $input->getArgument('remote');
$output = new ConsoleOutput();
$output = $output->section();
$this->currentUserService->commandLineViewer($input->getOption('viewer'), true);
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), '', true);
$filter = null;
if ($member !== '') {
$filter = $this->currentUserService->createFilterMember($member);
$filter = $this->federatedUserService->createFilterMember($member);
}
$circles = $this->getCircles($filter, $remote, $input->getOption('all'));
@ -187,21 +188,18 @@ class CirclesList extends Base {
/**
* @param Member|null $filter
* @param string $viewer
* @param string $remote
* @param bool $all
*
* @return Circle[]
* @throws InitiatorNotFoundException
* @throws InvalidItemException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws SignatureException
* @throws ViewerNotFoundException
* @throws CircleNotFoundException
* @throws UnknownRemoteException
* @throws NoUserException
*/
private function getCircles(?Member $filter, string $remote, bool $all = false): array {
if ($remote !== '') {

View file

@ -35,11 +35,11 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
use OC\Core\Command\Base;
use OCA\Circles\Db\MembershipRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Model\CurrentUser;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\ModelManager;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\CurrentUserService;
use OCA\Circles\Service\FederatedUserService;
use OCP\IGroupManager;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputInterface;
@ -73,8 +73,8 @@ class CirclesMemberships extends Base {
/** @var CircleService */
private $circleService;
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/**
@ -85,12 +85,12 @@ class CirclesMemberships extends Base {
* @param ModelManager $modelManager
* @param MembershipRequest $membershipRequest
* @param CircleService $circleService
* @param CurrentUserService $currentUserService
* @param FederatedUserService $federatedUserService
*/
public function __construct(
IUserManager $userManager, IGroupManager $groupManager, ModelManager $modelManager,
MembershipRequest $membershipRequest, CircleService $circleService,
CurrentUserService $currentUserService
FederatedUserService $federatedUserService
) {
parent::__construct();
$this->userManager = $userManager;
@ -99,7 +99,7 @@ class CirclesMemberships extends Base {
$this->membershipRequest = $membershipRequest;
$this->circleService = $circleService;
$this->currentUserService = $currentUserService;
$this->federatedUserService = $federatedUserService;
}
@ -153,10 +153,11 @@ class CirclesMemberships extends Base {
* @throws CircleNotFoundException
*/
private function indexLocalUser(string $userId): void {
$currentUser = new CurrentUser($userId);
$this->currentUserService->setCurrentUser($currentUser);
$currentUser = new FederatedUser();
$currentUser->setUserId($userId);
$this->federatedUserService->setCurrentUser($currentUser);
$this->currentUserService->updateMemberships();
$this->federatedUserService->updateMemberships();
}
}

View file

@ -46,7 +46,7 @@ use OCA\Circles\AppInfo\Application;
use OCA\Circles\Db\RemoteRequest;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteUidException;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\GlobalScaleService;
use OCA\Circles\Service\RemoteService;

View file

@ -42,10 +42,9 @@ use Exception;
use OC\Core\Command\Base;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Exceptions\GSStatusException;
use OCA\Circles\IMember;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\CurrentUserService;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -61,8 +60,8 @@ use Symfony\Component\Console\Output\OutputInterface;
class MembersAdd extends Base {
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/** @var CircleRequest */
private $circleRequest;
@ -78,16 +77,17 @@ class MembersAdd extends Base {
* MembersCreate constructor.
*
* @param CircleRequest $circleRequest
* @param CurrentUserService $currentUserService
* @param FederatedUserService $federatedUserService
* @param MemberService $memberService
* @param ConfigService $configService
*/
public function __construct(
CircleRequest $circleRequest, CurrentUserService $currentUserService, MemberService $memberService,
CircleRequest $circleRequest, FederatedUserService $federatedUserService,
MemberService $memberService,
ConfigService $configService
) {
parent::__construct();
$this->currentUserService = $currentUserService;
$this->federatedUserService = $federatedUserService;
$this->circleRequest = $circleRequest;
$this->memberService = $memberService;
@ -101,7 +101,7 @@ class MembersAdd extends Base {
->setDescription('Add a member to a Circle')
->addArgument('circle_id', InputArgument::REQUIRED, 'ID of the circle')
->addArgument('user', InputArgument::REQUIRED, 'username of the member')
->addOption('viewer', '', InputOption::VALUE_REQUIRED, 'set a viewer', '')
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
->addOption('type', '', InputOption::VALUE_REQUIRED, 'type of the user', Member::TYPE_USER);
}
@ -115,30 +115,16 @@ class MembersAdd extends Base {
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$circleId = $input->getArgument('circle_id');
$viewerId = $input->getOption('viewer');
$userId = $input->getArgument('user');
$userType = $input->getOption('type');
if ($viewerId !== '') {
$this->currentUserService->setLocalViewer($viewerId);
} else {
$localCircle = $this->circleRequest->getCircle($circleId);
if (!$this->configService->isLocalInstance($localCircle->getInstance())) {
throw new Exception('the Circle is not managed from this instance, please use --viewer');
}
//
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), $circleId, false);
// TODO: manage NO_OWNER circles
$owner = $localCircle->getOwner();
$this->currentUserService->setCurrentUser($owner);
}
$member = $this->currentUserService->createCurrentUser($userId, (int)$userType);
$member = $this->federatedUserService->createFederatedUser($userId, (int)$userType);
$this->memberService->addMember($circleId, $member);
//// $this->membersService->levelMember($circleId, $userId, DeprecatedMember::TYPE_USER, $instance, $level, true);
////
//// $member = $this->membersRequest->forceGetMember($circleId, $userId, DeprecatedMember::TYPE_USER, $instance);
//// echo json_encode($member, JSON_PRETTY_PRINT) . "\n";
// echo json_encode($member, JSON_PRETTY_PRINT) . "\n";
return 0;
}

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
@ -32,13 +34,12 @@ namespace OCA\Circles\Command;
use Exception;
use OC\Core\Command\Base;
use OC\User\NoUserException;
use OCA\Circles\Db\DeprecatedMembersRequest;
use OCA\Circles\Model\DeprecatedMember;
use OCA\Circles\Service\MembersService;
use OCP\IL10N;
use OCP\IUserManager;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -50,43 +51,39 @@ use Symfony\Component\Console\Output\OutputInterface;
class MembersLevel extends Base {
/** @var IL10N */
private $l10n;
private $memberRequest;
/** @var IUserManager */
private $userManager;
/** @var FederatedUserService */
private $federatedUserService;
/** @var DeprecatedMembersRequest */
private $membersRequest;
/** @var MembersService */
private $membersService;
/** @var MemberService */
private $memberService;
/**
* MembersLevel constructor.
*
* @param IL10N $l10n
* @param IUserManager $userManager
* @param DeprecatedMembersRequest $membersRequest
* @param MembersService $membersService
* @param MemberRequest $memberRequest
* @param FederatedUserService $federatedUserService
* @param MemberService $memberService
*/
public function __construct(
IL10N $l10n, IUserManager $userManager, DeprecatedMembersRequest $membersRequest, MembersService $membersService
MemberRequest $memberRequest, FederatedUserService $federatedUserService, MemberService $memberService
) {
parent::__construct();
$this->l10n = $l10n;
$this->userManager = $userManager;
$this->membersRequest = $membersRequest;
$this->membersService = $membersService;
$this->memberRequest = $memberRequest;
$this->federatedUserService = $federatedUserService;
$this->memberService = $memberService;
}
protected function configure() {
parent::configure();
$this->setName('circles:members:level')
->setDescription('Change level of a member')
->addArgument('member_id', InputArgument::REQUIRED, 'ID of the member')
->setDescription('Change the level of a member from a Circle')
->addArgument('member_id', InputArgument::REQUIRED, 'ID of the member from the Circle')
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
->addArgument('level', InputArgument::REQUIRED, 'new level');
}
@ -101,30 +98,19 @@ class MembersLevel extends Base {
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$memberId = $input->getArgument('member_id');
$level = $input->getArgument('level');
$levels = [
'member' => DeprecatedMember::LEVEL_MEMBER,
'moderator' => DeprecatedMember::LEVEL_MODERATOR,
'admin' => DeprecatedMember::LEVEL_ADMIN,
'owner' => DeprecatedMember::LEVEL_OWNER
];
if (!key_exists(strtolower($level), $levels)) {
throw new Exception('unknown level: ' . json_encode(array_keys($levels)));
}
$level = $levels[strtolower($level)];
$member = $this->membersService->getMemberById($memberId);
$this->membersService->levelMember(
$member->getCircleId(), $member->getUserId(), DeprecatedMember::TYPE_USER, $member->getInstance(), $level,
true
$member = $this->memberRequest->getMember($memberId);
echo json_encode($member, JSON_PRETTY_PRINT) . "\n";
$this->federatedUserService->commandLineInitiator(
$input->getOption('initiator'), $member->getCircleId()
);
$member = $this->membersRequest->forceGetMember(
$member->getCircleId(), $member->getUserId(), DeprecatedMember::TYPE_USER, $member->getInstance()
);
$level = $this->memberService->parseLevelString($input->getArgument('level'));
$this->memberService->memberLevel($memberId, $level);
// $member = $this->membersRequest->forceGetMember(
// $member->getCircleId(), $member->getUserId(), DeprecatedMember::TYPE_USER, $member->getInstance()
// );
echo json_encode($member, JSON_PRETTY_PRINT) . "\n";
return 0;

View file

@ -34,11 +34,12 @@ namespace OCA\Circles\Command;
use OC\Core\Command\Base;
use OC\User\NoUserException;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\ViewerNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\CurrentUserService;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
@ -56,8 +57,8 @@ use Symfony\Component\Console\Output\OutputInterface;
class MembersList extends Base {
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/** @var CircleService */
private $circleService;
@ -72,17 +73,18 @@ class MembersList extends Base {
/**
* MembersList constructor.
*
* @param CurrentUserService $currentUserService
* @param FederatedUserService $federatedUserService
* @param CircleService $circleService
* @param MemberService $memberService
* @param ConfigService $configService
*/
public function __construct(
CurrentUserService $currentUserService, CircleService $circleService, MemberService $memberService,
FederatedUserService $federatedUserService, CircleService $circleService,
MemberService $memberService,
ConfigService $configService
) {
parent::__construct();
$this->currentUserService = $currentUserService;
$this->federatedUserService = $federatedUserService;
$this->circleService = $circleService;
$this->memberService = $memberService;
$this->configService = $configService;
@ -92,10 +94,10 @@ class MembersList extends Base {
protected function configure() {
parent::configure();
$this->setName('circles:members:list')
->setDescription('listing members')
->setDescription('listing Members from a Circle')
->addArgument('circle_id', InputArgument::REQUIRED, 'ID of the circle')
->addOption('json', '', InputOption::VALUE_NONE, 'returns result as JSON')
->addOption('viewer', '', InputOption::VALUE_REQUIRED, 'add a viewer to the request', '');
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '');
}
@ -105,14 +107,16 @@ class MembersList extends Base {
*
* @return int
* @throws CircleNotFoundException
* @throws ViewerNotFoundException
* @throws InitiatorNotFoundException
* @throws NoUserException
* @throws OwnerNotFoundException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$circleId = $input->getArgument('circle_id');
$json = $input->getOption('json');
$this->currentUserService->commandLineViewer($input->getOption('viewer'), true);
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), $circleId, true);
$this->circleService->getCircle($circleId);
$members = $this->memberService->getMembers($circleId);
@ -126,7 +130,7 @@ class MembersList extends Base {
$output = $output->section();
$table = new Table($output);
$table->setHeaders(['ID', 'Username', 'Instance', 'Level']);
$table->setHeaders(['ID', 'Single ID', 'Username', 'Instance', 'Level']);
$table->render();
$local = $this->configService->getLocalInstance();
@ -134,6 +138,7 @@ class MembersList extends Base {
$table->appendRow(
[
$member->getId(),
$member->getSingleId(),
$member->getUserId(),
($member->getInstance() === $local) ? '' : $member->getInstance(),
Member::$DEF_LEVEL[$member->getLevel()]

View file

@ -40,12 +40,14 @@ use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Controller;
use Exception;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\RemoteDownstreamService;
use OCA\Circles\Service\RemoteService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
@ -107,12 +109,19 @@ class RemoteController extends Controller {
public function event(): DataResponse {
try {
$event = $this->extractEventFromRequest();
$result = $this->remoteDownstreamService->incomingEvent($event);
return $this->success($result);
} catch (Exception $e) {
return $this->fail($e);
return $this->fail($e, [], Http::STATUS_BAD_REQUEST);
}
try {
$this->remoteDownstreamService->requestedEvent($event);
} catch (FederatedEventException $e) {
$event->setOutcome($e->getMessage(), $e->getParams(), false);
} catch (Exception $e) {
$event->setOutcome($e->getMessage(), [], false);
}
return $this->successObj($event->getOutcome());
}
@ -184,20 +193,15 @@ class RemoteController extends Controller {
* @throws MalformedArrayException
* @throws SignatoryException
* @throws SignatureException
* @throws CircleNotFoundException
*/
private function extractEventFromRequest(): RemoteEvent {
private function extractEventFromRequest(): FederatedEvent {
$signed = $this->remoteService->incomingSignedRequest($this->configService->getLocalInstance());
$this->confirmRemoteInstance($signed);
$event = new RemoteEvent();
$event = new FederatedEvent();
$event->import(json_decode($signed->getBody(), true));
$event->setIncomingOrigin($signed->getOrigin());
if (!$event->hasCircle()) {
throw new CircleNotFoundException('Event contains no Circle');
}
return $event;
}

View file

@ -37,7 +37,7 @@ use Exception;
use OCA\Circles\Exceptions\GSStatusException;
use OCA\Circles\Model\GlobalScale\GSEvent;
use OCA\Circles\Service\RemoteDownstreamService;
use OCA\Circles\Service\RemoteEventService;
use OCA\Circles\Service\FederatedEventService;
use OCA\Circles\Service\RemoteUpstreamService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
@ -58,8 +58,8 @@ class RemoteWrapperController extends Controller {
use TNC21Controller;
/** @var RemoteEventService */
private $remoteEventService;
/** @var FederatedEventService */
private $federatedEventService;
/** @var RemoteUpstreamService */
private $remoteUpstreamService;
@ -73,17 +73,17 @@ class RemoteWrapperController extends Controller {
*
* @param string $appName
* @param IRequest $request
* @param RemoteEventService $remoteEventService
* @param FederatedEventService $federatedEventService
* @param RemoteUpstreamService $remoteUpstreamService
* @param RemoteDownstreamService $remoteDownstreamService
*/
public function __construct(
string $appName, IRequest $request,
RemoteEventService $remoteEventService, RemoteUpstreamService $remoteUpstreamService,
FederatedEventService $federatedEventService, RemoteUpstreamService $remoteUpstreamService,
RemoteDownstreamService $remoteDownstreamService
) {
parent::__construct($appName, $request);
$this->remoteEventService = $remoteEventService;
$this->federatedEventService = $federatedEventService;
$this->remoteUpstreamService = $remoteUpstreamService;
$this->remoteDownstreamService = $remoteDownstreamService;
}
@ -141,7 +141,7 @@ class RemoteWrapperController extends Controller {
}
}
$this->remoteEventService->manageResults($token);
$this->federatedEventService->manageResults($token);
// exit() or useless log will be generated
exit();

View file

@ -33,7 +33,7 @@ namespace OCA\Circles\Db;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\IMember;
use OCA\Circles\IFederatedUser;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Member;
@ -83,16 +83,16 @@ class CircleRequest extends CircleRequestBuilder {
/**
* @param Member|null $filter
* @param IMember|null $viewer
* @param IFederatedUser|null $initiator
*
* @return Circle[]
*/
public function getCircles(?Member $filter = null, ?IMember $viewer = null): array {
public function getCircles(?Member $filter = null, ?IFederatedUser $initiator = null): array {
$qb = $this->getCircleSelectSql();
$qb->leftJoinOwner();
if (!is_null($viewer)) {
$qb->limitToViewer($viewer);
if (!is_null($initiator)) {
$qb->limitToInitiator($initiator);
}
if (!is_null($filter)) {
@ -105,18 +105,18 @@ class CircleRequest extends CircleRequestBuilder {
/**
* @param string $id
* @param IMember|null $viewer
* @param IFederatedUser|null $initiator
*
* @return Circle
* @throws CircleNotFoundException
*/
public function getCircle(string $id, ?IMember $viewer = null): Circle {
public function getCircle(string $id, ?IFederatedUser $initiator = null): Circle {
$qb = $this->getCircleSelectSql();
$qb->limitToUniqueId($id);
$qb->leftJoinOwner();
if (!is_null($viewer)) {
$qb->limitToViewer($viewer);
if (!is_null($initiator)) {
$qb->limitToInitiator($initiator);
}
return $this->getItemFromRequest($qb);
@ -126,15 +126,15 @@ class CircleRequest extends CircleRequestBuilder {
/**
* method that return the single-user Circle based on a Viewer.
*
* @param IMember $viewer
* @param IFederatedUser $initiator
*
* @return Circle
* @throws CircleNotFoundException
*/
public function getViewerCircle(IMember $viewer): Circle {
public function getInitiatorCircle(IFederatedUser $initiator): Circle {
$qb = $this->getCircleSelectSql();
$qb->leftJoinOwner();
$qb->limitToMembership($viewer, Member::LEVEL_OWNER);
$qb->limitToMembership($initiator, Member::LEVEL_OWNER);
$qb->limitToConfig(Circle::CFG_SINGLE);
return $this->getItemFromRequest($qb);

View file

@ -34,8 +34,9 @@ namespace OCA\Circles\Db;
use daita\MySmallPhpTools\Db\Nextcloud\nc21\NC21ExtendedQueryBuilder;
use Doctrine\DBAL\Query\QueryBuilder;
use OC;
use OCA\Circles\IMember;
use OCA\Circles\IFederatedUser;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\ConfigService;
@ -47,6 +48,12 @@ use OCA\Circles\Service\ConfigService;
class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
const PREFIX_MEMBER = 'member_';
const PREFIX_OWNER = 'owner_';
const PREFIX_INITIATOR = 'initiator_';
const PREFIX_CIRCLE = 'circle_';
/** @var ConfigService */
private $configService;
@ -62,11 +69,11 @@ class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
/**
* @param IMember $member
* @param IFederatedUser $member
*
* @return string
*/
public function getInstance(IMember $member): string {
public function getInstance(IFederatedUser $member): string {
$instance = $member->getInstance();
return ($this->configService->isLocalInstance($instance)) ? '' : $instance;
@ -87,6 +94,14 @@ class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
$this->limitToDBFieldInt('config', $config);
}
/**
* @param string $singleId
*/
public function limitToSingleId(string $singleId): void {
$this->limitToDBField('single_id', $singleId, true);
}
/**
* @param string $host
*/
@ -96,124 +111,123 @@ class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
/**
* @param IMember $viewer
* @param IFederatedUser $initiator
* @param string $alias
*/
public function limitToViewer(IMember $viewer): void {
$this->leftJoinViewer($viewer, 'v');
$this->limitVisibility('v');
public function limitToInitiator(IFederatedUser $initiator, string $alias = ''): void {
$this->leftJoinInitiator($initiator, 'init', $alias);
$this->limitVisibility('init', $alias);
}
/**
* @param IMember $member
* @param IFederatedUser $member
* @param int $level
*/
public function limitToMembership(IMember $member, int $level = Member::LEVEL_MEMBER): void {
public function limitToMembership(IFederatedUser $member, int $level = Member::LEVEL_MEMBER): void {
if ($this->getType() !== QueryBuilder::SELECT) {
return;
}
$expr = $this->expr();
$pf = $this->getDefaultSelectAlias() . '.';
$this->selectAlias('m.user_id', 'member_user_id')
->selectAlias('m.user_type', 'member_user_type')
->selectAlias('m.member_id', 'member_member_id')
->selectAlias('m.circle_id', 'member_circle_id')
->selectAlias('m.instance', 'member_instance')
->selectAlias('m.cached_name', 'member_cached_name')
->selectAlias('m.cached_update', 'member_cached_update')
->selectAlias('m.status', 'member_status')
->selectAlias('m.level', 'member_level')
->selectAlias('m.note', 'member_note')
->selectAlias('m.contact_id', 'member_contact_id')
->selectAlias('m.contact_meta', 'member_contact_meta')
->selectAlias('m.joined', 'member_joined')
$alias = 'm';
$this->generateMemberSelectAlias($alias, self::PREFIX_MEMBER)
->leftJoin(
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, 'm',
$expr->eq('m.circle_id', $pf . 'unique_id')
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $alias,
$expr->eq($alias . '.circle_id', $this->getDefaultSelectAlias() . '.unique_id')
);
// TODO: Check in big table if it is better to put condition in andWhere() or in LeftJoin()
$this->andWhere(
$expr->andX(
$expr->eq('m.user_id', $this->createNamedParameter($member->getUserId())),
$expr->eq('m.user_type', $this->createNamedParameter($member->getUserType())),
$expr->eq('m.instance', $this->createNamedParameter($this->getInstance($member))),
$expr->gte('m.level', $this->createNamedParameter($level))
$expr->eq($alias . '.user_id', $this->createNamedParameter($member->getUserId())),
$expr->eq($alias . '.user_type', $this->createNamedParameter($member->getUserType())),
$expr->eq($alias . '.instance', $this->createNamedParameter($this->getInstance($member))),
$expr->gte($alias . '.level', $this->createNamedParameter($level))
)
);
}
/**
*
* @param FederatedUser|null $initiator
*/
public function leftJoinOwner() {
public function leftJoinCircle(?FederatedUser $initiator = null) {
if ($this->getType() !== QueryBuilder::SELECT) {
return;
}
$expr = $this->expr();
$pf = $this->getDefaultSelectAlias() . '.';
$this->selectAlias('o.user_id', 'owner_user_id')
->selectAlias('o.user_type', 'owner_user_type')
->selectAlias('o.member_id', 'owner_member_id')
->selectAlias('o.circle_id', 'owner_circle_id')
->selectAlias('o.instance', 'owner_instance')
->selectAlias('o.cached_name', 'owner_cached_name')
->selectAlias('o.cached_update', 'owner_cached_update')
->selectAlias('o.status', 'owner_status')
->selectAlias('o.level', 'owner_level')
->selectAlias('o.note', 'owner_note')
->selectAlias('o.contact_id', 'owner_contact_id')
->selectAlias('o.contact_meta', 'owner_contact_meta')
->selectAlias('o.joined', 'owner_joined')
$alias = 'c';
$this->generateCircleSelectAlias($alias, self::PREFIX_CIRCLE)
->leftJoin(
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, 'o',
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_CIRCLE, $alias,
$expr->andX(
$expr->eq('o.circle_id', $pf . 'unique_id'),
$expr->eq('o.level', $this->createNamedParameter(Member::LEVEL_OWNER))
$expr->eq($alias . '.unique_id', $this->getDefaultSelectAlias() . '.circle_id')
)
);
if (!is_null($initiator)) {
$this->leftJoinOwner($alias);
$this->limitToInitiator($initiator, $alias);
}
}
/**
* @param string $circleTableAlias
*/
public function leftJoinOwner(string $circleTableAlias = '') {
if ($this->getType() !== QueryBuilder::SELECT) {
return;
}
if ($circleTableAlias === '') {
$circleTableAlias = $this->getDefaultSelectAlias();
}
$expr = $this->expr();
$alias = 'o';
$this->generateMemberSelectAlias($alias, self::PREFIX_OWNER)
->leftJoin(
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $alias,
$expr->andX(
$expr->eq($alias . '.circle_id', $circleTableAlias . '.unique_id'),
$expr->eq($alias . '.level', $this->createNamedParameter(Member::LEVEL_OWNER))
)
);
}
/**
* Left join members to filter userId as viewer.
* Left join members to filter userId as initiator.
*
* @param IMember $viewer
* @param IFederatedUser $initiator
* @param string $alias
* @param string $aliasCircle
*/
public function leftJoinViewer(IMember $viewer, string $alias = 'v') {
public function leftJoinInitiator(
IFederatedUser $initiator, string $alias = 'init', string $aliasCircle = ''
) {
if ($this->getType() !== QueryBuilder::SELECT) {
return;
}
$expr = $this->expr();
$pf = $this->getDefaultSelectAlias() . '.';
$this->selectAlias('v.user_id', 'viewer_user_id')
->selectAlias('v.user_type', 'viewer_user_type')
->selectAlias('v.member_id', 'viewer_member_id')
->selectAlias('v.circle_id', 'viewer_circle_id')
->selectAlias('v.instance', 'viewer_instance')
->selectAlias('v.cached_name', 'viewer_cached_name')
->selectAlias('v.cached_update', 'viewer_cached_update')
->selectAlias('v.status', 'viewer_status')
->selectAlias('v.level', 'viewer_level')
->selectAlias('v.note', 'viewer_note')
->selectAlias('v.contact_id', 'viewer_contact_id')
->selectAlias('v.contact_meta', 'viewer_contact_meta')
->selectAlias('v.joined', 'viewer_joined')
$aliasCircle = ($aliasCircle === '') ? $this->getDefaultSelectAlias() : $aliasCircle;
$this->generateMemberSelectAlias($alias, self::PREFIX_INITIATOR)
->leftJoin(
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, 'v',
$this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $alias,
$expr->andX(
$expr->eq('v.circle_id', $pf . 'unique_id'),
$expr->eq('v.user_id', $this->createNamedParameter($viewer->getUserId())),
$expr->eq('v.user_type', $this->createNamedParameter($viewer->getUserType())),
$expr->eq('v.instance', $this->createNamedParameter($this->getInstance($viewer)))
$expr->eq($alias . '.circle_id', $aliasCircle . '.unique_id'),
$expr->eq($alias . '.user_id', $this->createNamedParameter($initiator->getUserId())),
$expr->eq($alias . '.user_type', $this->createNamedParameter($initiator->getUserType())),
$expr->eq(
$alias . '.instance', $this->createNamedParameter($this->getInstance($initiator))
)
)
);
}
@ -221,13 +235,15 @@ class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
/**
* @param string $alias
* @param string $aliasCircle
*/
protected function limitVisibility(string $alias = 'v') {
protected function limitVisibility(string $alias = 'init', string $aliasCircle = '') {
$expr = $this->expr();
$aliasCircle = ($aliasCircle === '') ? $this->getDefaultSelectAlias() : $aliasCircle;
// Visibility to non-member is
// - 0 (default), if viewer is member
// - 2 (Personal), if viewer is owner)
// - 0 (default), if initiator is member
// - 2 (Personal), if initiator is owner)
// - 4 (Visible to everyone)
$orX = $expr->orX();
$orX->add(
@ -235,20 +251,20 @@ class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
);
$orX->add(
$expr->andX(
$expr->bitwiseAnd($this->getDefaultSelectAlias() . '.config', Circle::CFG_PERSONAL),
$expr->bitwiseAnd($aliasCircle . '.config', Circle::CFG_PERSONAL),
$expr->eq($alias . '.level', $this->createNamedParameter(Member::LEVEL_OWNER))
)
);
$orX->add($expr->bitwiseAnd($this->getDefaultSelectAlias() . '.config', Circle::CFG_VISIBLE));
$orX->add($expr->bitwiseAnd($aliasCircle . '.config', Circle::CFG_VISIBLE));
$this->andWhere($orX);
// TODO: add a filter for allowing 1, 128
// - 1 means hidden to front-end, filtering
$bitHidden = $expr->bitwiseAnd($this->getDefaultSelectAlias() . '.config', Circle::CFG_SINGLE);
$bitHidden = $expr->bitwiseAnd($aliasCircle . '.config', Circle::CFG_SINGLE);
$this->andWhere($this->createFunction('NOT') . $bitHidden);
// - 128 means fully hidden, filtering
$bitHidden = $expr->bitwiseAnd($this->getDefaultSelectAlias() . '.config', Circle::CFG_HIDDEN);
$bitHidden = $expr->bitwiseAnd($aliasCircle . '.config', Circle::CFG_HIDDEN);
$this->andWhere($this->createFunction('NOT') . $bitHidden);
@ -278,5 +294,50 @@ class CoreQueryBuilder extends NC21ExtendedQueryBuilder {
}
/**
* @param string $alias
* @param string $prefix
*
* @return $this
*/
private function generateCircleSelectAlias(string $alias, string $prefix): self {
$this->selectAlias($alias . '.unique_id', $prefix . 'unique_id')
->selectAlias($alias . '.name', $prefix . 'name')
->selectAlias($alias . '.alt_name', $prefix . 'alt_name')
->selectAlias($alias . '.description', $prefix . 'description')
->selectAlias($alias . '.settings', $prefix . 'settings')
->selectAlias($alias . '.config', $prefix . 'config')
->selectAlias($alias . '.contact_addressbook', $prefix . 'contact_addressbook')
->selectAlias($alias . '.contact_groupname', $prefix . 'contact_groupname')
->selectAlias($alias . '.creation', $prefix . 'creation');
return $this;
}
/**
* @param string $alias
* @param string $prefix
*
* @return $this
*/
private function generateMemberSelectAlias(string $alias, string $prefix): self {
$this->selectAlias($alias . '.circle_id', $prefix . 'circle_id')
->selectAlias($alias . '.single_id', $prefix . 'single_id')
->selectAlias($alias . '.user_id', $prefix . 'user_id')
->selectAlias($alias . '.user_type', $prefix . 'user_type')
->selectAlias($alias . '.member_id', $prefix . 'member_id')
->selectAlias($alias . '.instance', $prefix . 'instance')
->selectAlias($alias . '.cached_name', $prefix . 'cached_name')
->selectAlias($alias . '.cached_update', $prefix . 'cached_update')
->selectAlias($alias . '.status', $prefix . 'status')
->selectAlias($alias . '.level', $prefix . 'level')
->selectAlias($alias . '.note', $prefix . 'note')
->selectAlias($alias . '.contact_id', $prefix . 'contact_id')
->selectAlias($alias . '.contact_meta', $prefix . 'contact_meta')
->selectAlias($alias . '.joined', $prefix . 'joined');
return $this;
}
}

View file

@ -32,7 +32,9 @@ declare(strict_types=1);
namespace OCA\Circles\Db;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Member;
@ -50,6 +52,7 @@ class MemberRequest extends MemberRequestBuilder {
public function save(Member $member): void {
$qb = $this->getMemberInsertSql();
$qb->setValue('circle_id', $qb->createNamedParameter($member->getCircleId()))
->setValue('single_id', $qb->createNamedParameter($member->getSingleId()))
->setValue('member_id', $qb->createNamedParameter($member->getId()))
->setValue('user_id', $qb->createNamedParameter($member->getUserId()))
->setValue('user_type', $qb->createNamedParameter($member->getUserType()))
@ -77,5 +80,25 @@ class MemberRequest extends MemberRequestBuilder {
return $this->getItemsFromRequest($qb);
}
/**
* @param string $memberId
* @param FederatedUser|null $initiator
*
* @return Member
* @throws MemberNotFoundException
*/
public function getMember(string $memberId, ?FederatedUser $initiator = null): Member {
$qb = $this->getMemberSelectSql();
$qb->limitToMemberId($memberId);
if (!is_null($initiator)) {
$qb->leftJoinCircle($initiator);
}
return $this->getItemFromRequest($qb);
}
}

View file

@ -74,8 +74,9 @@ class MemberRequestBuilder extends CoreRequestBuilder {
protected function getMemberSelectSql(): CoreQueryBuilder {
$qb = $this->getQueryBuilder();
$qb->select(
'm.user_id', 'm.instance', 'm.user_type', 'm.circle_id', 'm.level', 'm.status', 'm.note',
'm.contact_id', 'm.member_id', 'm.cached_name', 'm.cached_update', 'm.contact_meta', 'm.joined'
'm.circle_id', 'm.single_id', 'm.user_id', 'm.instance', 'm.user_type', 'm.level', 'm.status',
'm.note', 'm.contact_id', 'm.member_id', 'm.cached_name', 'm.cached_update', 'm.contact_meta',
'm.joined'
)
->from(self::TABLE_MEMBER, 'm')
->orderBy('m.joined')

View file

@ -35,7 +35,7 @@ namespace OCA\Circles\Db;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteUidException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Model\Federated\RemoteInstance;
/**

View file

@ -34,7 +34,7 @@ namespace OCA\Circles\Db;
use daita\MySmallPhpTools\Exceptions\RowNotFoundException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Model\Federated\RemoteInstance;
/**

View file

@ -33,7 +33,7 @@ namespace OCA\Circles\Db;
use OCA\Circles\Model\GlobalScale\GSWrapper;
use OCA\Circles\Model\Remote\RemoteWrapper;
use OCA\Circles\Model\Federated\RemoteWrapper;
/**

View file

@ -34,7 +34,7 @@ namespace OCA\Circles\Db;
use daita\MySmallPhpTools\Exceptions\RowNotFoundException;
use OCA\Circles\Exceptions\RemoteWrapperNotFoundException;
use OCA\Circles\Model\Remote\RemoteWrapper;
use OCA\Circles\Model\Federated\RemoteWrapper;
/**

View file

@ -28,12 +28,15 @@
namespace OCA\Circles\Exceptions;
use Exception;
/**
* Class RemoteEventException
* Class FederatedEventDSyncException
*
* @package OCA\Circles\Exceptions
*/
class RemoteEventException extends \Exception {
class FederatedEventDSyncException extends Exception {
}

View file

@ -0,0 +1,88 @@
<?php
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2017
* @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\Circles\Exceptions;
use Exception;
use JsonSerializable;
use Throwable;
/**
* Class FederatedEventException
*
* @package OCA\Circles\Exceptions
*/
class FederatedEventException extends Exception implements JsonSerializable {
/** @var array */
private $params;
/**
* FederatedEventException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '', array $params = [], int $code = 0, ?Throwable $previous = null
) {
parent::__construct($message, $code, $previous);
$this->setParams($params);
}
/**
* @param array $params
*/
private function setParams(array $params): void {
$this->params = $params;
}
/**
* @return array
*/
public function getParams(): array {
return $this->params;
}
/**
* @return mixed|void
*/
public function jsonSerialize(): array {
return [
'message' => $this->getMessage(),
'params' => $this->getParams()
];
}
}

View file

@ -33,7 +33,7 @@ namespace OCA\Circles\Exceptions;
use Exception;
class ViewerNotConfirmedException extends Exception {
class InitiatorNotConfirmedException extends Exception {
}

View file

@ -33,7 +33,7 @@ namespace OCA\Circles\Exceptions;
use Exception;
class ViewerNotFoundException extends Exception {
class InitiatorNotFoundException extends Exception {
}

View file

@ -29,27 +29,27 @@ declare(strict_types=1);
*/
namespace OCA\Circles\RemoteEvents;
namespace OCA\Circles\FederatedItems;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\IRemoteEvent;
use OCA\Circles\IRemoteEventBypassLocalCircleCheck;
use OCA\Circles\IRemoteEventMustBeLocal;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemBypassLocalCircleCheck;
use OCA\Circles\IFederatedItemMustBeLocal;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Service\ConfigService;
/**
* Class CircleCreate
*
* @package OCA\Circles\RemoteEvents
* @package OCA\Circles\FederatedItems
*/
class CircleCreate implements
IRemoteEvent,
IRemoteEventBypassLocalCircleCheck,
IRemoteEventMustBeLocal {
IFederatedItem,
IFederatedItemBypassLocalCircleCheck,
IFederatedItemMustBeLocal {
/** @var CircleRequest */
@ -61,6 +61,7 @@ class CircleCreate implements
/** @var ConfigService */
private $configService;
/**
* CircleCreate constructor.
*
@ -78,18 +79,18 @@ class CircleCreate implements
/**
* Circles are created on the original instance, using IRemoteEventMustBeLocal
* Circles are created on the original instance, using IFederatedItemMustBeLocal
*
* @param RemoteEvent $event
* @param FederatedEvent $event
*/
public function verify(RemoteEvent $event): void {
public function verify(FederatedEvent $event): void {
}
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*/
public function manage(RemoteEvent $event): void {
public function manage(FederatedEvent $event): void {
if (!$event->hasCircle()) {
return;
}
@ -106,7 +107,7 @@ class CircleCreate implements
/**
* @param RemoteEvent[] $events
* @param FederatedEvent[] $events
*/
public function result(array $events): void {
}

View file

@ -29,7 +29,7 @@ declare(strict_types=1);
*/
namespace OCA\Circles\RemoteEvents;
namespace OCA\Circles\FederatedItems;
use daita\MySmallPhpTools\Traits\TStringTools;
@ -38,15 +38,16 @@ use OC\User\NoUserException;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\Exceptions\MemberTypeNotFoundException;
use OCA\Circles\Exceptions\RemoteEventException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\TokenDoesNotExistException;
use OCA\Circles\Exceptions\UserTypeNotFoundException;
use OCA\Circles\IMember;
use OCA\Circles\IRemoteEvent;
use OCA\Circles\IFederatedUser;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemMustHaveMember;
use OCA\Circles\Model\DeprecatedCircle;
use OCA\Circles\Model\DeprecatedMember;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\SharesToken;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
@ -61,7 +62,9 @@ use OCP\Util;
*
* @package OCA\Circles\GlobalScale
*/
class MemberAdd implements IRemoteEvent {
class MemberAdd implements
IFederatedItem,
IFederatedItemMustHaveMember {
use TStringTools;
@ -100,25 +103,22 @@ class MemberAdd implements IRemoteEvent {
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @throws MemberLevelException
* @throws NoUserException
* @throws RemoteEventException
* @throws FederatedEventException
* @throws UserTypeNotFoundException
* @throws \OCA\Circles\Exceptions\MembersLimitException
*/
public function verify(RemoteEvent $event): void {
if (!$event->hasMember()) {
throw new RemoteEventException('event have no member linked');
}
public function verify(FederatedEvent $event): void {
$member = $event->getMember();
$circle = $event->getCircle();
$viewer = $circle->getViewer();
$initiator = $circle->getInitiator();
if ($viewer->getLevel() < Member::LEVEL_MODERATOR) {
throw new MemberLevelException('Viewer have no rights to add members to this Circles');
if ($initiator->getLevel() < Member::LEVEL_MODERATOR) {
throw new MemberLevelException('Insufficient rights to add members to this Circle');
}
$this->confirmMemberFormat($member);
@ -171,10 +171,10 @@ class MemberAdd implements IRemoteEvent {
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
*/
public function manage(RemoteEvent $event): void {
public function manage(FederatedEvent $event): void {
//$circle = $event->getCircle();
$member = $event->getMember();
// if ($member->getJoined() === '') {
@ -211,7 +211,7 @@ class MemberAdd implements IRemoteEvent {
/**
* @param RemoteEvent[] $events
* @param FederatedEvent[] $events
*
* @throws Exception
*/
@ -264,12 +264,12 @@ class MemberAdd implements IRemoteEvent {
/**
* confirm the format of UserId, based on UserType.
*
* @param IMember $member
* @param IFederatedUser $member
*
* @throws UserTypeNotFoundException
* @throws NoUserException
*/
private function confirmMemberFormat(IMember $member): void {
private function confirmMemberFormat(IFederatedUser $member): void {
switch ($member->getUserType()) {
case Member::TYPE_USER:
$this->confirmMemberTypeUser($member);
@ -283,11 +283,11 @@ class MemberAdd implements IRemoteEvent {
/**
* @param IMember $member
* @param IFederatedUser $member
*
* @throws NoUserException
*/
private function confirmMemberTypeUser(IMember $member): void {
private function confirmMemberTypeUser(IFederatedUser $member): void {
if ($this->configService->isLocalInstance($member->getInstance())) {
$user = $this->userManager->get($member->getUserId());
if ($user === null) {

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
/**
@ -27,61 +29,56 @@
*/
namespace OCA\Circles\GlobalScale;
namespace OCA\Circles\FederatedItems;
use Exception;
use OCA\Circles\Exceptions\CircleDoesNotExistException;
use OCA\Circles\Exceptions\ConfigNoCircleAvailableException;
use OCA\Circles\Exceptions\GlobalScaleDSyncException;
use OCA\Circles\Exceptions\GlobalScaleEventException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\MemberDoesNotExistException;
use OCA\Circles\Exceptions\MemberIsNotModeratorException;
use OCA\Circles\Exceptions\MemberIsNotOwnerException;
use OCA\Circles\Exceptions\MemberIsOwnerException;
use OCA\Circles\Exceptions\MemberTypeCantEditLevelException;
use OCA\Circles\Exceptions\ModeratorIsNotHighEnoughException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemMustHaveMember;
use OCA\Circles\Model\DeprecatedCircle;
use OCA\Circles\Model\GlobalScale\GSEvent;
use OCA\Circles\Model\DeprecatedMember;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\GlobalScale\GSEvent;
use OCA\Circles\Model\Member;
/**
* Class MemberLevel
*
* @package OCA\Circles\GlobalScale
* @package OCA\Circles\FederatedItems
*/
class MemberLevel extends AGlobalScaleEvent {
class MemberLevel implements
IFederatedItem,
IFederatedItemMustHaveMember {
/**
* @param GSEvent $event
* @param bool $localCheck
* @param FederatedEvent $event
*
* @param bool $mustBeChecked
*
* @throws CircleDoesNotExistException
* @throws ConfigNoCircleAvailableException
* @throws GlobalScaleDSyncException
* @throws GlobalScaleEventException
* @throws MemberTypeCantEditLevelException
* @throws Exception
* @throws FederatedEventException
* @throws MemberDoesNotExistException
* @throws MemberIsNotModeratorException
* @throws MemberIsOwnerException
* @throws ModeratorIsNotHighEnoughException
*/
public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChecked = true): void {
parent::verify($event, $localCheck, true);
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$member = $event->getMember();
$level = $event->getData()
->gInt('level');
if ($member->getLevel() === $level) {
throw new GlobalScaleDSyncException('level is not changed during the process');
throw new FederatedEventException('This member already have the selected level');
}
$member->levelHasToBeEditable();
$circle = $event->getDeprecatedCircle();
if ($level === DeprecatedMember::LEVEL_OWNER) {
$this->verifySwitchOwner($event, $circle, $member);
if ($level === Member::LEVEL_OWNER) {
// $this->verifySwitchOwner($event, $circle, $member);
} else {
$this->verifyMemberLevel($event, $circle, $member, $level);
}
@ -90,35 +87,33 @@ class MemberLevel extends AGlobalScaleEvent {
/**
* @param GSEvent $event
*
* @throws Exception
* @param FederatedEvent $event
*/
public function manage(GSEvent $event): void {
public function manage(FederatedEvent $event): void {
$level = $event->getData()
->gInt('level');
$member = $event->getMember();
$this->cleanMember($member);
$member->setLevel($level);
$this->membersRequest->updateMemberLevel($member);
if ($level === DeprecatedMember::LEVEL_OWNER) {
$circle = $event->getDeprecatedCircle();
$isMod = $circle->getOwner();
if ($isMod->getInstance() === '') {
$isMod->setInstance($event->getSource());
}
$isMod->setLevel(DeprecatedMember::LEVEL_ADMIN);
$this->membersRequest->updateMemberLevel($isMod);
}
//
// $member = $event->getMember();
// $this->cleanMember($member);
//
// $member->setLevel($level);
// $this->membersRequest->updateMemberLevel($member);
//
// if ($level === DeprecatedMember::LEVEL_OWNER) {
// $circle = $event->getDeprecatedCircle();
// $isMod = $circle->getOwner();
// if ($isMod->getInstance() === '') {
// $isMod->setInstance($event->getSource());
// }
//
// $isMod->setLevel(DeprecatedMember::LEVEL_ADMIN);
// $this->membersRequest->updateMemberLevel($isMod);
// }
}
/**
* @param GSEvent[] $events
* @param FederatedEvent[] $events
*/
public function result(array $events): void {
}
@ -135,7 +130,9 @@ class MemberLevel extends AGlobalScaleEvent {
* @throws MemberIsNotModeratorException
* @throws ModeratorIsNotHighEnoughException
*/
private function verifyMemberLevel(GSEvent $event, DeprecatedCircle $circle, DeprecatedMember $member, int $level) {
private function verifyMemberLevel(
GSEvent $event, DeprecatedCircle $circle, DeprecatedMember $member, int $level
) {
$member->hasToBeMember();
$member->cantBeOwner();

View file

@ -32,28 +32,28 @@ declare(strict_types=1);
namespace OCA\Circles;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\Model\Federated\FederatedEvent;
/**
* Interface IRemoteEvent
* Interface IFederatedItem
*
* @package OCA\Circles
*/
interface IRemoteEvent {
interface IFederatedItem {
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*/
public function verify(RemoteEvent $event): void;
public function verify(FederatedEvent $event): void;
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*/
public function manage(RemoteEvent $event): void;
public function manage(FederatedEvent $event): void;
/**
* @param RemoteEvent[] $events
* @param FederatedEvent[] $events
*/
public function result(array $events): void;

View file

@ -33,11 +33,11 @@ namespace OCA\Circles;
/**
* Interface IRemoteEvent
* Interface IFederatedItemBypassInitiatorCheck
*
* @package OCA\Circles
*/
interface IRemoteEventBypassLocalCircleCheck {
interface IFederatedItemBypassInitiatorCheck {
}

View file

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles;
/**
* Interface IFederatedItemBypassLocalCircleCheck
*
* @package OCA\Circles
*/
interface IFederatedItemBypassLocalCircleCheck {
}

View file

@ -33,11 +33,11 @@ namespace OCA\Circles;
/**
* Interface IRemoteEvent
* Interface IFederatedItemMustBeLocal
*
* @package OCA\Circles
*/
interface IRemoteEventBypassViewerCheck {
interface IFederatedItemMustBeLocal {
}

View file

@ -33,11 +33,11 @@ namespace OCA\Circles;
/**
* Interface IRemoteEvent
* Interface IFederatedItemMustHaveMember
*
* @package OCA\Circles
*/
interface IRemoteEventMustBeLocal {
interface IFederatedItemMustHaveMember {
}

View file

@ -33,13 +33,13 @@ namespace OCA\Circles;
/**
* Interface IMember
* Interface IFederatedUser
*
* @package OCA\Circles
*/
interface IMember {
interface IFederatedUser {
public function getId(): string;
public function getSingleId(): string;
public function getUserId(): string;
@ -47,7 +47,5 @@ interface IMember {
public function getInstance(): string;
public function importFromIMember(IMember $member): self;
}

View file

@ -92,6 +92,21 @@ class Version0021Date20210105123456 extends SimpleMigrationStep {
} catch (SchemaException $e) {
}
try {
$circles = $schema->getTable('circle_members');
if (!$circles->hasColumn('single_id')) {
$circles->addColumn(
'single_id', 'string', [
'notnull' => false,
'length' => 15
]
);
}
} catch (SchemaException $e) {
}
if (!$schema->hasTable('circle_remotes')) {
$table = $schema->createTable('circle_remotes');
$table->addColumn(

View file

@ -38,6 +38,7 @@ use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Convert;
use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime;
use JsonSerializable;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
@ -93,10 +94,11 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
const CFG_ROOT = 2048; // Circle cannot be inside another Circle
const CFG_FEDERATED = 4096; // Federated
const ID_LENGTH = 14;
const ID_LENGTH = 15;
static $DEF = [
1 => 'S|Single',
1 => 'S|Single',
2 => 'P|Personal',
8 => 'V|Visible',
16 => 'O|Open',
@ -133,7 +135,7 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
private $members = [];
/** @var Member */
private $viewer;
private $initiator;
/** @var array */
private $settings = [];
@ -312,12 +314,12 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
/**
* @param Member $viewer
* @param Member $initiator
*
* @return Circle
*/
public function setViewer(Member $viewer): self {
$this->viewer = $viewer;
public function setInitiator(Member $initiator): self {
$this->initiator = $initiator;
return $this;
}
@ -325,15 +327,15 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
/**
* @return Member
*/
public function getViewer(): Member {
return $this->viewer;
public function getInitiator(): Member {
return $this->initiator;
}
/**
* @return bool
*/
public function hasViewer(): bool {
return ($this->viewer !== null);
public function hasInitiator(): bool {
return ($this->initiator !== null);
}
/**
@ -526,6 +528,13 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
} catch (InvalidItemException $e) {
}
try {
/** @var Member $owner */
$initiator = $this->convert($this->getArray('initiator', $data), Member::class);
$this->setInitiator($initiator);
} catch (InvalidItemException $e) {
}
return $this;
}
@ -549,6 +558,10 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
$arr['owner'] = $this->getOwner();
}
if ($this->hasInitiator()) {
$arr['initiator'] = $this->getInitiator();
}
if ($this->getManager()->isFullDetails()) {
$arr['memberOf'] = $this->memberOf();
}
@ -559,25 +572,31 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
/**
* @param array $data
* @param string $prefix
*
* @return INC21QueryRow
* @throws CircleNotFoundException
*/
public function importFromDatabase(array $data): INC21QueryRow {
$this->setId($this->get('unique_id', $data))
->setName($this->get('name', $data))
->setAltName($this->get('alt_name', $data))
->setConfig($this->getInt('config', $data))
->setInstance($this->get('instance', $data))
->setSettings($this->getArray('settings', $data))
->setContactAddressBook($this->getInt('contact_addressbook', $data))
->setContactGroupName($this->get('contact_groupname', $data))
->setDescription($this->get('description', $data));
public function importFromDatabase(array $data, string $prefix = ''): INC21QueryRow {
if (!array_key_exists($prefix . 'unique_id', $data)) {
throw new CircleNotFoundException();
}
$creation = $this->get('creation', $data);
$this->setId($this->get($prefix . 'unique_id', $data))
->setName($this->get($prefix . 'name', $data))
->setAltName($this->get($prefix . 'alt_name', $data))
->setConfig($this->getInt($prefix . 'config', $data))
->setInstance($this->get($prefix . 'instance', $data))
->setSettings($this->getArray($prefix . 'settings', $data))
->setContactAddressBook($this->getInt($prefix . 'contact_addressbook', $data))
->setContactGroupName($this->get($prefix . 'contact_groupname', $data))
->setDescription($this->get($prefix . 'description', $data));
$creation = $this->get($prefix . 'creation', $data);
$this->setCreation(DateTime::createFromFormat('Y-m-d H:i:s', $creation)->getTimestamp());
$this->getManager()->importOwnerFromDatabase($this, $data);
$this->getManager()->importViewerFromDatabase($this, $data);
$this->getManager()->importInitiatorFromDatabase($this, $data);
return $this;
}
@ -587,9 +606,11 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
* @param Circle $circle
*
* @return bool
* @throws OwnerNotFoundException
*/
public function compareWith(Circle $circle): bool {
if ($this->getId() !== $circle->getId()
|| $this->getInstance() !== $circle->getInstance()
|| $this->getConfig() !== $circle->getConfig()) {
return false;
}
@ -600,7 +621,14 @@ class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSe
return false;
}
if ($this->hasInitiator()
&& (!$circle->hasInitiator()
|| !$this->getInitiator()->compareWith($circle->getInitiator()))) {
return false;
}
return true;
}
}

View file

@ -29,30 +29,29 @@ declare(strict_types=1);
*/
namespace OCA\Circles\Model\Remote;
namespace OCA\Circles\Model\Federated;
use daita\MySmallPhpTools\Model\SimpleDataStore;
use daita\MySmallPhpTools\Traits\TArrayTools;
use JsonSerializable;
use OCA\Circles\Exceptions\ViewerNotConfirmedException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Member;
/**
* Class RemoteEvent
* Class FederatedEvent
*
* @package OCA\Circles\Model\Remote
* @package OCA\Circles\Model\Federated
*/
class RemoteEvent implements JsonSerializable {
class FederatedEvent implements JsonSerializable {
const SEVERITY_LOW = 1;
const SEVERITY_HIGH = 3;
const BYPASS_LOCALCIRCLECHECK = 1;
const BYPASS_VIEWERCHECK = 2;
const BYPASS_INITIATORCHECK = 2;
use TArrayTools;
@ -76,6 +75,9 @@ class RemoteEvent implements JsonSerializable {
/** @var int */
private $severity = self::SEVERITY_LOW;
/** @var SimpleDataStore */
private $outcome;
/** @var SimpleDataStore */
private $result;
@ -100,7 +102,7 @@ class RemoteEvent implements JsonSerializable {
/**
* RemoteEvent constructor.
* FederatedEvent constructor.
*
* @param string $class
*/
@ -108,6 +110,7 @@ class RemoteEvent implements JsonSerializable {
$this->class = $class;
$this->data = new SimpleDataStore();
$this->result = new SimpleDataStore();
$this->outcome = new SimpleDataStore();
}
@ -204,7 +207,7 @@ class RemoteEvent implements JsonSerializable {
/**
* @param bool $verifiedViewer
*
* @return RemoteEvent
* @return FederatedEvent
*/
public function setVerifiedViewer(bool $verifiedViewer): self {
$this->verifiedViewer = $verifiedViewer;
@ -212,48 +215,48 @@ class RemoteEvent implements JsonSerializable {
return $this;
}
/**
* @return bool
*/
public function isVerifiedViewer(): bool {
return $this->verifiedViewer;
}
// /**
// * @return bool
// */
// public function isVerifiedViewer(): bool {
// return $this->verifiedViewer;
// }
/**
* @throws ViewerNotConfirmedException
*/
public function confirmVerifiedViewer(): void {
if ($this->isVerifiedViewer()) {
return;
}
throw new ViewerNotConfirmedException();
}
// /**
// * @throws InitiatorNotConfirmedException
// */
// public function confirmVerifiedViewer(): void {
// if ($this->isVerifiedViewer()) {
// return;
// }
//
// throw new InitiatorNotConfirmedException();
// }
/**
* @param bool $verifiedCircle
*
* @return RemoteEvent
*/
public function setVerifiedCircle(bool $verifiedCircle): self {
$this->verifiedCircle = $verifiedCircle;
return $this;
}
/**
* @return bool
*/
public function isVerifiedCircle(): bool {
return $this->verifiedCircle;
}
// /**
// * @param bool $verifiedCircle
// *
// * @return FederatedEvent
// */
// public function setVerifiedCircle(bool $verifiedCircle): self {
// $this->verifiedCircle = $verifiedCircle;
//
// return $this;
// }
//
// /**
// * @return bool
// */
// public function isVerifiedCircle(): bool {
// return $this->verifiedCircle;
// }
/**
* @param string $wrapperToken
*
* @return RemoteEvent
* @return FederatedEvent
*/
public function setWrapperToken(string $wrapperToken): self {
$this->wrapperToken = $wrapperToken;
@ -359,6 +362,33 @@ class RemoteEvent implements JsonSerializable {
}
/**
* @return SimpleDataStore
*/
public function getOutcome(): SimpleDataStore {
return $this->outcome;
}
/**
* @param string $message
* @param array $params
* @param bool $success
*
* @return $this
*/
public function setOutcome(string $message, array $params = [], bool $success = true): self {
$this->outcome = new SimpleDataStore(
[
'message' => $message,
'params' => $params,
'success' => $success
]
);
return $this;
}
/**
* @return SimpleDataStore
*/
@ -417,6 +447,7 @@ class RemoteEvent implements JsonSerializable {
'data' => $this->getData(),
'result' => $this->getResult(),
'source' => $this->getSource(),
'outcome' => $this->getOutcome(),
'async' => $this->isAsync()
];
@ -434,7 +465,7 @@ class RemoteEvent implements JsonSerializable {
/**
* @param int $flag
*
* @return RemoteEvent
* @return FederatedEvent
*/
public function bypass(int $flag): self {
if (!$this->canBypass($flag)) {

View file

@ -29,7 +29,7 @@ declare(strict_types=1);
*/
namespace OCA\Circles\Model\Remote;
namespace OCA\Circles\Model\Federated;
use daita\MySmallPhpTools\Db\Nextcloud\nc21\INC21QueryRow;

View file

@ -29,7 +29,7 @@ declare(strict_types=1);
*/
namespace OCA\Circles\Model\Remote;
namespace OCA\Circles\Model\Federated;
use daita\MySmallPhpTools\Db\Nextcloud\nc21\INC21QueryRow;
@ -57,14 +57,14 @@ class RemoteWrapper implements INC21QueryRow, JsonSerializable {
/** @var string */
private $token = '';
/** @var RemoteEvent */
/** @var FederatedEvent */
private $event;
/** @var string */
private $instance = '';
/** @var int */
private $severity = RemoteEvent::SEVERITY_LOW;
private $severity = FederatedEvent::SEVERITY_LOW;
/** @var int */
private $status = 0;
@ -97,18 +97,18 @@ class RemoteWrapper implements INC21QueryRow, JsonSerializable {
/**
* @return RemoteEvent
* @return FederatedEvent
*/
public function getEvent(): RemoteEvent {
public function getEvent(): FederatedEvent {
return $this->event;
}
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @return self
*/
public function setEvent(RemoteEvent $event): self {
public function setEvent(FederatedEvent $event): self {
$this->event = $event;
return $this;
@ -206,10 +206,10 @@ class RemoteWrapper implements INC21QueryRow, JsonSerializable {
public function import(array $data): self {
$this->setToken($this->get('token', $data));
$this->setInstance($this->get('instance', $data));
$this->setSeverity($this->getInt('severity', $data, RemoteEvent::SEVERITY_LOW));
$this->setSeverity($this->getInt('severity', $data, FederatedEvent::SEVERITY_LOW));
$this->setStatus($this->getInt('status', $data, self::STATUS_INIT));
$event = new RemoteEvent();
$event = new FederatedEvent();
$event->import($this->getArray('event', $data));
$this->setEvent($event);
@ -241,10 +241,10 @@ class RemoteWrapper implements INC21QueryRow, JsonSerializable {
public function importFromDatabase(array $data): INC21QueryRow {
$this->setToken($this->get('token', $data));
$this->setInstance($this->get('instance', $data));
$this->setSeverity($this->getInt('severity', $data, RemoteEvent::SEVERITY_LOW));
$this->setSeverity($this->getInt('severity', $data, FederatedEvent::SEVERITY_LOW));
$this->setStatus($this->getInt('status', $data, self::STATUS_INIT));
$event = new RemoteEvent();
$event = new FederatedEvent();
$event->import($this->getArray('event', $data));
$this->setEvent($event);

View file

@ -35,22 +35,22 @@ use daita\MySmallPhpTools\Db\Nextcloud\nc21\INC21QueryRow;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\INC21Convert;
use daita\MySmallPhpTools\Traits\TArrayTools;
use JsonSerializable;
use OCA\Circles\IMember;
use OCA\Circles\IFederatedUser;
/**
* Class Viewer
* Class FederatedUser
*
* @package OCA\Circles\Model
*/
class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21QueryRow, JsonSerializable {
class FederatedUser extends ManagedModel implements IFederatedUser, INC21Convert, INC21QueryRow, JsonSerializable {
use TArrayTools;
/** @var string */
private $id = '';
private $singleId = '';
/** @var string */
private $userId;
@ -66,26 +66,31 @@ class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21Qu
/**
* Viewer constructor.
* FederatedUser constructor.
*
* @param string $userId
* @param int $type
* @param string $instance
*/
public function __construct(string $userId = '', $instance = '', int $type = Member::TYPE_USER) {
$this->userId = $userId;
$this->setInstance($instance);
$this->userType = $type;
public function __construct() {
}
public function set(string $userId = '', $instance = '', int $type = Member::TYPE_USER): self {
$this->userId = $userId;
$this->setInstance($instance);
$this->userType = $type;
return $this;
}
/**
* @param string $id
* @param string $singleId
*
* @return self
*/
public function setId(string $id): self {
$this->id = $id;
public function setSingleId(string $singleId): self {
$this->singleId = $singleId;
return $this;
}
@ -93,8 +98,8 @@ class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21Qu
/**
* @return string
*/
public function getId(): string {
return $this->id;
public function getSingleId(): string {
return $this->singleId;
}
@ -182,25 +187,13 @@ class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21Qu
}
/**
* @param IMember $member
*
* @return self
*/
public function importFromIMember(IMember $member): IMember {
$this->getManager()->importFromIMember($this, $member);
return $this;
}
/**
* @param array $data
*
* @return $this
*/
public function import(array $data): INC21Convert {
$this->setId($this->get('id', $data));
$this->setSingleId($this->get('id', $data));
$this->setUserId($this->get('user_id', $data));
$this->setUserType($this->getInt('user_type', $data));
$this->setInstance($this->get('instance', $data));
@ -215,7 +208,7 @@ class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21Qu
*/
public function jsonSerialize(): array {
return [
'id' => $this->getId(),
'id' => $this->getSingleId(),
'user_id' => $this->getUserId(),
'user_type' => $this->getUserType(),
'instance' => $this->getInstance(),
@ -231,7 +224,7 @@ class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21Qu
* @return INC21QueryRow
*/
public function importFromDatabase(array $data, string $prefix = ''): INC21QueryRow {
$this->setId($this->get($prefix . 'member_id', $data));
$this->setSingleId($this->get($prefix . 'member_id', $data));
$this->setUserId($this->get($prefix . 'user_id', $data));
$this->setUserType($this->getInt($prefix . 'user_type', $data));
$this->setInstance($this->get($prefix . 'instance', $data));
@ -240,3 +233,4 @@ class CurrentUser extends ManagedModel implements IMember, INC21Convert, INC21Qu
}
}

View file

@ -32,6 +32,8 @@ declare(strict_types=1);
namespace OCA\Circles\Model;
use OCA\Circles\IFederatedUser;
/**
* Class ManagedModel
*
@ -55,5 +57,18 @@ class ManagedModel {
return $this->modelManager;
}
/** @noinspection PhpPossiblePolymorphicInvocationInspection */
public function importFromIFederatedUser(IFederatedUser $orig): void {
if (!($this instanceof IFederatedUser)) {
return;
}
$this->setSingleId($orig->getSingleId());
$this->setUserId($orig->getUserId());
$this->setUserType($orig->getUserType());
$this->setInstance($orig->getInstance());
}
}

View file

@ -37,7 +37,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime;
use JsonSerializable;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\IMember;
use OCA\Circles\IFederatedUser;
/**
@ -45,7 +45,7 @@ use OCA\Circles\IMember;
*
* @package OCA\Circles\Model
*/
class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRow, JsonSerializable {
class Member extends ManagedModel implements IFederatedUser, INC21Convert, INC21QueryRow, JsonSerializable {
use TArrayTools;
@ -70,7 +70,7 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
const STATUS_BLOCKED = 'Blocked';
const STATUS_KICKED = 'Kicked';
const ID_LENGTH = 14;
const ID_LENGTH = 15;
static $DEF_LEVEL = [
1 => 'Member',
@ -87,13 +87,16 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
private $circleId = '';
/** @var string */
private $userId;
/** @var int */
private $userType;
private $singleId = '';
/** @var string */
private $instance;
private $userId = '';
/** @var int */
private $userType = self::TYPE_USER;
/** @var string */
private $instance = '';
/** @var int */
private $level = 0;
@ -116,21 +119,18 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
/** @var string */
private $contactMeta = '';
/** @var Circle */
private $circle;
/** @var int */
private $joined = 0;
/**
* Member constructor.
*
* @param string $userId
* @param int $type
* @param string $instance
*/
public function __construct(string $userId = '', int $type = self::TYPE_USER, $instance = '') {
$this->userId = $userId;
$this->userType = $type;
$this->instance = $instance;
public function __construct() {
}
@ -172,6 +172,28 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
}
/**
* This should replace user_id, user_type and instance; and will use the data from Circle with
* Config=CFG_SINGLE
*
* @param string $singleId
*
* @return $this
*/
public function setSingleId(string $singleId): self {
$this->singleId = $singleId;
return $this;
}
/**
* @return string
*/
public function getSingleId(): string {
return $this->singleId;
}
/**
* @param string $userId
*
@ -363,6 +385,32 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
}
/**
* @param Circle $circle
*
* @return self
*/
public function setCircle(Circle $circle): self {
$this->circle = $circle;
return $this;
}
/**
* @return Circle
*/
public function getCircle(): Circle {
return $this->circle;
}
/**
* @return bool
*/
public function hasCircle(): bool {
return (!is_null($this->circle));
}
/**
* @param int $joined
*
@ -398,11 +446,12 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
public function compareWith(Member $member): bool {
if ($this->getId() !== $member->getId()
|| $this->getCircleId() !== $member->getCircleId()
|| $this->getSingleId() !== $member->getSingleId()
|| $this->getUserId() !== $member->getUserId()
|| $this->getUserType() <> $member->getUserType()
|| $this->getInstance() !== $member->getInstance()
|| $this->getLevel() <> $member->getLevel()
|| $this->getStatus() !== $member->getStatus()
|| $this->getInstance() !== $member->getInstance()) {
|| $this->getStatus() !== $member->getStatus()) {
return false;
}
@ -410,18 +459,6 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
}
/**
* @param IMember $member
*
* @return self
*/
public function importFromIMember(IMember $member): IMember {
$this->getManager()->importFromIMember($this, $member);
return $this;
}
/**
* @param array $data
*
@ -430,6 +467,7 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
public function import(array $data): INC21Convert {
$this->setId($this->get('id', $data));
$this->setCircleId($this->get('circle_id', $data));
$this->setSingleId($this->get('single_id', $data));
$this->setUserId($this->get('user_id', $data));
$this->setUserType($this->getInt('user_type', $data));
$this->setInstance($this->get('instance', $data));
@ -450,10 +488,11 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
* @return string[]
*/
public function jsonSerialize(): array {
return array_filter(
$arr = array_filter(
[
'id' => $this->getId(),
'circle_id' => $this->getCircleId(),
'single_id' => $this->getSingleId(),
'user_id' => $this->getUserId(),
'user_type' => $this->getUserType(),
'instance' => $this->getInstance(),
@ -467,6 +506,12 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
'joined' => $this->getJoined()
]
);
if ($this->hasCircle()) {
$arr['circle'] = $this->getCircle();
}
return $arr;
}
@ -484,6 +529,7 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
$this->setId($this->get($prefix . 'member_id', $data));
$this->setCircleId($this->get($prefix . 'circle_id', $data));
$this->setSingleId($this->get($prefix . 'single_id', $data));
$this->setUserId($this->get($prefix . 'user_id', $data));
$this->setUserType($this->getInt($prefix . 'user_type', $data));
$this->setInstance($this->get($prefix . 'instance', $data));
@ -508,6 +554,10 @@ class Member extends ManagedModel implements IMember, INC21Convert, INC21QueryRo
$this->setInstance($this->get('_params.local', $data));
}
if ($prefix === '') {
$this->getManager()->importCircleFromDatabase($this, $data);
}
return $this;
}

View file

@ -32,9 +32,10 @@ declare(strict_types=1);
namespace OCA\Circles\Model;
use OCA\Circles\Db\CoreQueryBuilder;
use OCA\Circles\Db\MembershipRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\IMember;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\MemberService;
@ -90,11 +91,11 @@ class ModelManager {
/**
* @param CurrentUser $currentUser
* @param FederatedUser $federatedUser
*/
public function getMemberships(CurrentUser $currentUser): void {
$memberships = $this->membershipRequest->getMemberships($currentUser->getId());
$currentUser->setMemberships($memberships);
public function getMemberships(FederatedUser $federatedUser): void {
$memberships = $this->membershipRequest->getMemberships($federatedUser->getSingleId());
$federatedUser->setMemberships($memberships);
}
@ -107,6 +108,19 @@ class ModelManager {
}
/**
* @param Member $member
* @param array $data
*/
public function importCircleFromDatabase(Member $member, array $data) {
try {
$circle = new Circle();
$circle->importFromDatabase($data, CoreQueryBuilder::PREFIX_CIRCLE);
$member->setCircle($circle);
} catch (CircleNotFoundException $e) {
}
}
/**
* @param Circle $circle
* @param array $data
@ -114,7 +128,7 @@ class ModelManager {
public function importOwnerFromDatabase(Circle $circle, array $data): void {
try {
$owner = new Member();
$owner->importFromDatabase($data, 'owner_');
$owner->importFromDatabase($data, CoreQueryBuilder::PREFIX_OWNER);
$circle->setOwner($owner);
} catch (MemberNotFoundException $e) {
}
@ -125,11 +139,11 @@ class ModelManager {
* @param Circle $circle
* @param array $data
*/
public function importViewerFromDatabase(Circle $circle, array $data): void {
public function importInitiatorFromDatabase(Circle $circle, array $data): void {
try {
$viewer = new Member();
$viewer->importFromDatabase($data, 'viewer_');
$circle->setViewer($viewer);
$initiator = new Member();
$initiator->importFromDatabase($data, CoreQueryBuilder::PREFIX_INITIATOR);
$circle->setInitiator($initiator);
} catch (MemberNotFoundException $e) {
}
}
@ -166,7 +180,7 @@ class ModelManager {
/**
* @return string
*/
public function getLocalInstance() {
public function getLocalInstance(): string {
return $this->configService->getLocalInstance();
}
@ -185,16 +199,5 @@ class ModelManager {
return $this->fullDetails;
}
/**
* @param IMember $dest
* @param IMember $orig
*/
public function importFromIMember(IMember $dest, IMember $orig): void {
$dest->setUserId($orig->getUserId());
$dest->setUserType($orig->getUserType());
$dest->setInstance($orig->getInstance());
}
}

View file

@ -39,14 +39,14 @@ use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\MembersLimitException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteEventException;
use OCA\Circles\Exceptions\ViewerNotConfirmedException;
use OCA\Circles\Exceptions\ViewerNotFoundException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\CurrentUser;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\RemoteEvents\CircleCreate;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\FederatedItems\CircleCreate;
/**
@ -67,11 +67,11 @@ class CircleService {
/** @var MemberRequest */
private $memberRequest;
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/** @var RemoteEventService */
private $remoteEventService;
/** @var FederatedEventService */
private $federatedEventService;
/** @var ConfigService */
private $configService;
@ -82,36 +82,36 @@ class CircleService {
*
* @param CircleRequest $circleRequest
* @param MemberRequest $memberRequest
* @param CurrentUserService $currentUserService
* @param RemoteEventService $remoteEventService
* @param FederatedUserService $federatedUserService
* @param FederatedEventService $federatedEventService
* @param ConfigService $configService
*/
public function __construct(
CircleRequest $circleRequest, MemberRequest $memberRequest, CurrentUserService $currentUserService,
RemoteEventService $remoteEventService, ConfigService $configService
CircleRequest $circleRequest, MemberRequest $memberRequest, FederatedUserService $federatedUserService,
FederatedEventService $federatedEventService, ConfigService $configService
) {
$this->circleRequest = $circleRequest;
$this->memberRequest = $memberRequest;
$this->currentUserService = $currentUserService;
$this->remoteEventService = $remoteEventService;
$this->federatedUserService = $federatedUserService;
$this->federatedEventService = $federatedEventService;
$this->configService = $configService;
}
/**
* @param string $name
* @param CurrentUser|null $owner
* @param FederatedUser|null $owner
*
* @return Circle
* @throws OwnerNotFoundException
* @throws RemoteEventException
* @throws ViewerNotFoundException
* @throws ViewerNotConfirmedException
* @throws FederatedEventException
* @throws InitiatorNotFoundException
* @throws InitiatorNotConfirmedException
*/
public function create(string $name, ?CurrentUser $owner = null): Circle {
$this->currentUserService->mustHaveCurrentUser();
public function create(string $name, ?FederatedUser $owner = null): Circle {
$this->federatedUserService->mustHaveCurrentUser();
if (is_null($owner)) {
$owner = $this->currentUserService->getCurrentUser();
$owner = $this->federatedUserService->getCurrentUser();
}
$circle = new Circle();
@ -119,17 +119,17 @@ class CircleService {
$circle->setId($this->token(Circle::ID_LENGTH));
$member = new Member();
$member->importFromIMember($owner);
$member->importFromIFederatedUser($owner);
$member->setId($this->token(Member::ID_LENGTH))
->setCircleId($circle->getId())
->setLevel(Member::LEVEL_OWNER)
->setStatus(Member::STATUS_MEMBER);
$circle->setOwner($member)
->setViewer($member);
->setInitiator($member);
$event = new RemoteEvent(CircleCreate::class);
$event = new FederatedEvent(CircleCreate::class);
$event->setCircle($circle);
$this->remoteEventService->newEvent($event);
$this->federatedEventService->newEvent($event);
return $circle;
}
@ -139,12 +139,12 @@ class CircleService {
* @param Member|null $filter
*
* @return Circle[]
* @throws ViewerNotFoundException
* @throws InitiatorNotFoundException
*/
public function getCircles(?Member $filter = null): array {
$this->currentUserService->mustHaveCurrentUser();
$this->federatedUserService->mustHaveCurrentUser();
return $this->circleRequest->getCircles($filter, $this->currentUserService->getCurrentUser());
return $this->circleRequest->getCircles($filter, $this->federatedUserService->getCurrentUser());
}
@ -153,12 +153,12 @@ class CircleService {
*
* @return Circle
* @throws CircleNotFoundException
* @throws ViewerNotFoundException
* @throws InitiatorNotFoundException
*/
public function getCircle(string $circleId): Circle {
$this->currentUserService->mustHaveCurrentUser();
$this->federatedUserService->mustHaveCurrentUser();
return $this->circleRequest->getCircle($circleId, $this->currentUserService->getCurrentUser());
return $this->circleRequest->getCircle($circleId, $this->federatedUserService->getCurrentUser());
}

View file

@ -33,69 +33,56 @@ namespace OCA\Circles\Service;
use daita\MySmallPhpTools\ActivityPub\Nextcloud\nc21\NC21Signature;
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
use daita\MySmallPhpTools\Exceptions\SignatoryException;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21Request;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Request;
use daita\MySmallPhpTools\Traits\TStringTools;
use OC;
use OC\Security\IdentityProof\Signer;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\RemoteRequest;
use OCA\Circles\Db\RemoteWrapperRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\JsonException;
use OCA\Circles\Exceptions\ModelException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteEventException;
use OCA\Circles\Exceptions\ViewerNotConfirmedException;
use OCA\Circles\IRemoteEvent;
use OCA\Circles\IRemoteEventBypassLocalCircleCheck;
use OCA\Circles\IRemoteEventBypassViewerCheck;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemBypassInitiatorCheck;
use OCA\Circles\IFederatedItemBypassLocalCircleCheck;
use OCA\Circles\IFederatedItemMustBeLocal;
use OCA\Circles\IFederatedItemMustHaveMember;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCA\Circles\Model\Federated\RemoteWrapper;
use OCA\Circles\Model\GlobalScale\GSWrapper;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Model\Remote\RemoteWrapper;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\IUserSession;
use ReflectionClass;
use ReflectionException;
/**
* Class RemoteService
* Class FederatedEventService
*
* @package OCA\Circles\Service
*/
class RemoteEventService extends NC21Signature {
class FederatedEventService extends NC21Signature {
use TNC21Request;
use TStringTools;
/** @var IURLGenerator */
private $urlGenerator;
/** @var IUserManager */
private $userManager;
/** @var IUserSession */
private $userSession;
/** @var Signer */
private $signer;
/** @var RemoteWrapperRequest */
private $remoteWrapperRequest;
/** @var RemoteRequest */
private $remoteRequest;
/** @var CircleRequest */
private $circleRequest;
/** @var RemoteUpstreamService */
private $remoteUpstreamService;
/** @var ConfigService */
private $configService;
@ -105,38 +92,21 @@ class RemoteEventService extends NC21Signature {
/**
* GlobalScaleService constructor.
* FederatedEventService constructor.
*
* @param IURLGenerator $urlGenerator
* @param IUserManager $userManager
* @param IUserSession $userSession
* @param Signer $signer
* @param RemoteWrapperRequest $remoteWrapperRequest
* @param RemoteRequest $remoteRequest
* @param CircleRequest $circleRequest
* @param RemoteUpstreamService $remoteUpstreamService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
IURLGenerator $urlGenerator,
IUserManager $userManager,
IUserSession $userSession,
Signer $signer,
RemoteWrapperRequest $remoteWrapperRequest,
RemoteRequest $remoteRequest,
CircleRequest $circleRequest,
ConfigService $configService,
MiscService $miscService
RemoteWrapperRequest $remoteWrapperRequest, RemoteRequest $remoteRequest,
RemoteUpstreamService $remoteUpstreamService, ConfigService $configService
) {
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
$this->userSession = $userSession;
$this->signer = $signer;
$this->remoteWrapperRequest = $remoteWrapperRequest;
$this->remoteRequest = $remoteRequest;
$this->circleRequest = $circleRequest;
$this->remoteUpstreamService = $remoteUpstreamService;
$this->configService = $configService;
$this->miscService = $miscService;
}
@ -144,63 +114,69 @@ class RemoteEventService extends NC21Signature {
* Called when creating a new Event.
* This method will manage the event locally and upstream the payload if needed.
*
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @throws RemoteEventException
* @throws InitiatorNotConfirmedException
* @throws OwnerNotFoundException
* @throws ViewerNotConfirmedException
* @throws FederatedEventException
* @throws RequestNetworkException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws UnknownRemoteException
* @throws SignatoryException
*/
public function newEvent(RemoteEvent $event): void {
public function newEvent(FederatedEvent $event): void {
$event->setSource($this->configService->getLocalInstance());
if (!$event->hasCircle()) {
throw new RemoteEventException('Event does not contains Circle');
}
try {
$gs = $this->getRemoteEvent($event);
} catch (RemoteEventException $e) {
$federatedItem = $this->getFederatedItem($event, true);
} catch (FederatedEventException $e) {
$this->e($e);
throw $e;
}
$this->confirmViewer($event);
// TODO :: UNCOMMENT UNCOMMENT UNCOMMENT !! this is only commented in order to test something
$this->confirmInitiator($event, true);
try {
if ($this->configService->isLocalInstance($event->getCircle()->getInstance())) {
$gs->verify($event);
if (!$event->isAsync()) {
$gs->manage($event);
}
$this->initBroadcast($event);
} else {
// $this->confirmEvent($event);
if ($this->configService->isLocalInstance($event->getCircle()->getInstance())) {
$federatedItem->verify($event);
if (!$event->isAsync()) {
$federatedItem->manage($event);
}
} catch (CircleNotFoundException $e) {
$this->e($e, ['event' => $event]);
}
$this->initBroadcast($event);
} else {
$this->remoteUpstreamService->confirmEvent($event);
}
}
/**
* This confirmation is optional, method is just here to avoid going too far away on the process
*
* @param RemoteEvent $event
* @param FederatedEvent $event
* @param bool $local
*
* @throws ViewerNotConfirmedException
* @throws InitiatorNotConfirmedException
*/
private function confirmViewer(RemoteEvent $event): void {
if ($event->canBypass(RemoteEvent::BYPASS_VIEWERCHECK)) {
public function confirmInitiator(FederatedEvent $event, bool $local = false): void {
if ($event->canBypass(FederatedEvent::BYPASS_INITIATORCHECK)) {
return;
}
$circle = $event->getCircle();
if (!$circle->hasViewer()
|| !$this->configService->isLocalInstance(
$circle->getViewer()->getInstance()
)) {
throw new ViewerNotConfirmedException('viewer does not exist or is not local');
if (!$circle->hasInitiator()) {
throw new InitiatorNotConfirmedException('initiator does not exist');
}
if ($local) {
if (!$this->configService->isLocalInstance($circle->getInitiator()->getInstance())) {
throw new InitiatorNotConfirmedException('initiator is not local');
}
} else {
if ($circle->getInitiator()->getInstance() !== $event->getIncomingOrigin()) {
throw new InitiatorNotConfirmedException('initiator must belong to remote instance');
}
}
}
@ -244,48 +220,78 @@ class RemoteEventService extends NC21Signature {
/**
* // TODO Rename Model/RemoteEvent and/or IRemoteEvent
* @param FederatedEvent $event
* @param bool $local
*
* @param RemoteEvent $event
*
* @return IRemoteEvent
* @throws RemoteEventException
* @return IFederatedItem
* @throws FederatedEventException
*/
public function getRemoteEvent(RemoteEvent $event): IRemoteEvent {
public function getFederatedItem(FederatedEvent $event, bool $local = false): IFederatedItem {
$class = $event->getClass();
try {
$test = new ReflectionClass($class);
} catch (ReflectionException $e) {
throw new RemoteEventException('ReflectionException with ' . $class . ': ' . $e->getMessage());
throw new FederatedEventException('ReflectionException with ' . $class . ': ' . $e->getMessage());
}
if (!in_array(IRemoteEvent::class, $test->getInterfaceNames())) {
throw new RemoteEventException($class . ' does not implements IRemoteEvent');
if (!in_array(IFederatedItem::class, $test->getInterfaceNames())) {
throw new FederatedEventException($class . ' does not implements IFederatedItem');
}
$gs = OC::$server->get($class);
if (!$gs instanceof IRemoteEvent) {
throw new RemoteEventException($class . ' not an IRemoteEvent');
$item = OC::$server->get($class);
if (!$item instanceof IFederatedItem) {
throw new FederatedEventException($class . ' not an IFederatedItem');
}
$this->setRemoteEventBypass($event, $gs);
$this->setFederatedEventBypass($event, $item);
$this->confirmMustHaveCondition($event, $item, $local);
return $gs;
return $item;
}
/**
* Some event might need to bypass some checks
*
* @param RemoteEvent $event
* @param IRemoteEvent $gs
* @param FederatedEvent $event
* @param IFederatedItem $gs
*/
private function setRemoteEventBypass(RemoteEvent $event, IRemoteEvent $gs) {
if ($gs instanceof IRemoteEventBypassLocalCircleCheck) {
$event->bypass(RemoteEvent::BYPASS_LOCALCIRCLECHECK);
private function setFederatedEventBypass(FederatedEvent $event, IFederatedItem $gs) {
if ($gs instanceof IFederatedItemBypassLocalCircleCheck) {
$event->bypass(FederatedEvent::BYPASS_LOCALCIRCLECHECK);
}
if ($gs instanceof IRemoteEventBypassViewerCheck) {
$event->bypass(RemoteEvent::BYPASS_VIEWERCHECK);
if ($gs instanceof IFederatedItemBypassInitiatorCheck) {
$event->bypass(FederatedEvent::BYPASS_INITIATORCHECK);
}
}
/**
* Some event might need to bypass some checks
*
* @param FederatedEvent $event
* @param IFederatedItem $item
* @param bool $local
*
* @throws FederatedEventException
*/
private function confirmMustHaveCondition(
FederatedEvent $event,
IFederatedItem $item,
bool $local = false
) {
if (!$event->hasCircle()) {
throw new FederatedEventException('FederatedItem has no Circle linked');
}
if ($item instanceof IFederatedItemMustHaveMember && !$event->hasMember()) {
throw new FederatedEventException('FederatedItem has no Member linked');
}
if ($event->hasMember() && !($item instanceof IFederatedItemMustHaveMember)) {
throw new FederatedEventException(
get_class($item) . ' does not implements IFederatedItemMustHaveMember '
);
}
if ($item instanceof IFederatedItemMustBeLocal && !$local) {
throw new FederatedEventException('FederatedItem must be local');
}
}
@ -293,9 +299,9 @@ class RemoteEventService extends NC21Signature {
/**
* async the process, generate a local request that will be closed.
*
* @param RemoteEvent $event
* @param FederatedEvent $event
*/
public function initBroadcast(RemoteEvent $event): void {
public function initBroadcast(FederatedEvent $event): void {
$instances = $this->getInstances($event->isAsync());
if (empty($instances)) {
return;
@ -396,47 +402,11 @@ class RemoteEventService extends NC21Signature {
}
try {
$gs = $this->getRemoteEvent($event);
$gs = $this->getFederatedItem($event);
$gs->result($events);
} catch (RemoteEventException $e) {
} catch (FederatedEventException $e) {
}
}
/**
* @param RemoteEvent $event
*/
private function confirmEvent(RemoteEvent $event): void {
// $this->signEvent($event);
$circle = $event->getCircle();
$owner = $circle->getOwner();
$path = $this->urlGenerator->linkToRoute('circles.RemoteWrapper.event');
$request = new NC21Request($path, Request::TYPE_POST);
$this->configService->configureRequest($request);
$request->basedOnUrl($owner->getInstance());
$request->setDataSerialize($event);
$result = $this->retrieveJson($request);
$this->debug('confirming RemoteEvent', ['event' => $event, 'request' => $request]);
//
// if ($this->getInt('status', $result) === 0) {
// throw new GlobalScaleEventException($this->get('error', $result));
// }
// $updatedData = $this->getArray('event', $result);
// $this->miscService->log('updatedEvent: ' . json_encode($updatedData), 0);
// if (!empty($updatedData)) {
// $updated = new GSEvent();
// try {
// $updated->import($updatedData);
// $event = $updated;
// } catch (Exception $e) {
// }
// }
}
}

View file

@ -40,22 +40,23 @@ use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Db\MembershipRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\UserTypeNotFoundException;
use OCA\Circles\Exceptions\ViewerNotFoundException;
use OCA\Circles\IMember;
use OCA\Circles\IFederatedUser;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\CurrentUser;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\Membership;
use OCP\IUserManager;
/**
* Class ViewerService
* Class FederatedUserService
*
* @package OCA\Circles\Service
*/
class CurrentUserService {
class FederatedUserService {
use TArrayTools;
@ -79,7 +80,7 @@ class CurrentUserService {
private $configService;
/** @var CurrentUser */
/** @var FederatedUser */
private $currentUser = null;
/** @var bool */
@ -87,7 +88,7 @@ class CurrentUserService {
/**
* ViewerService constructor.
* FederatedUserService constructor.
*
* @param IUserManager $userManager
* @param MembershipRequest $membershipRequest
@ -113,34 +114,30 @@ class CurrentUserService {
* @throws CircleNotFoundException
* @throws NoUserException
*/
public function setLocalViewer(string $userId): void {
$this->currentUser = $this->createLocalCurrentUser($userId);
public function setLocalInitiator(string $userId): void {
$this->currentUser = $this->createLocalFederatedUser($userId);
}
/**
* @param IMember $currentUser
* @param IFederatedUser $federatedUser
*
* @throws CircleNotFoundException
*/
public function setCurrentUser(IMember $currentUser): void {
if ($currentUser instanceof Member) {
$tmp = new CurrentUser();
$tmp->importFromIMember($currentUser);
$currentUser = $tmp;
public function setCurrentUser(IFederatedUser $federatedUser): void {
if (!($federatedUser instanceof FederatedUser)) {
$tmp = new FederatedUser();
$tmp->importFromIFederatedUser($federatedUser);
$federatedUser = $tmp;
}
// if ($currentUser->getInstance() === '') {
// $currentUser->setInstance($this->configService->getLocalInstance());
// }
$this->currentUser = $currentUser;
$this->fillSingleCircleId($this->currentUser);
$this->fillSingleCircleId($federatedUser);
$this->currentUser = $federatedUser;
}
/**
* @return CurrentUser|null
* @return FederatedUser|null
*/
public function getCurrentUser(): ?CurrentUser {
public function getCurrentUser(): ?FederatedUser {
return $this->currentUser;
}
@ -152,14 +149,14 @@ class CurrentUserService {
}
/**
* @throws ViewerNotFoundException
* @throws InitiatorNotFoundException
*/
public function mustHaveCurrentUser(): void {
if ($this->bypass) {
return;
}
if (!$this->hasCurrentUser()) {
throw new ViewerNotFoundException();
throw new InitiatorNotFoundException();
}
}
@ -174,36 +171,38 @@ class CurrentUserService {
/**
* @param string $userId
*
* @return CurrentUser
* @return FederatedUser
* @throws CircleNotFoundException
* @throws NoUserException
*/
public function createLocalCurrentUser(string $userId): CurrentUser {
public function createLocalFederatedUser(string $userId): FederatedUser {
$user = $this->userManager->get($userId);
if ($user === null) {
throw new NoUserException('user ' . $userId . ' not found');
}
$currentUser = new CurrentUser($user->getUID());
$this->fillSingleCircleId($currentUser);
$federatedUser = new FederatedUser();
$federatedUser->set($user->getUID());
$this->fillSingleCircleId($federatedUser);
return $currentUser;
return $federatedUser;
}
/**
* @param string $userId
* @param string $federatedId
* @param int $userType
*
* @return CurrentUser
* @return FederatedUser
* @throws CircleNotFoundException
* @throws NoUserException
* @throws UserTypeNotFoundException
*/
public function createCurrentUser(string $userId, int $userType = Member::TYPE_USER): CurrentUser {
public function createFederatedUser(string $federatedId, int $userType = Member::TYPE_USER
): FederatedUser {
switch ($userType) {
case Member::TYPE_USER:
return $this->createCurrentUserTypeUser($userId);
return $this->createFederatedUserTypeUser($federatedId);
}
throw new UserTypeNotFoundException();
@ -212,11 +211,11 @@ class CurrentUserService {
/**
* @param string $userId
*
* @return CurrentUser
* @return FederatedUser
* @throws CircleNotFoundException
* @throws NoUserException
*/
public function createCurrentUserTypeUser(string $userId): CurrentUser {
public function createFederatedUserTypeUser(string $userId): FederatedUser {
$userId = trim($userId, '@');
if (strpos($userId, '@') === false) {
$instance = $this->configService->getLocalInstance();
@ -225,31 +224,51 @@ class CurrentUserService {
}
if ($this->configService->isLocalInstance($instance)) {
return $this->createLocalCurrentUser($userId);
return $this->createLocalFederatedUser($userId);
} else {
return new CurrentUser($userId, $instance, Member::TYPE_USER);
$federatedUser = new FederatedUser();
$federatedUser->set($userId, $instance, Member::TYPE_USER);
return $federatedUser;
}
}
/**
* some ./occ commands allows to add a Viewer
* some ./occ commands allows to add an Initiator
* TODO: manage non-user type
*
* @param string $userId
* @param string $circleId
* @param bool $bypass
*
* @throws CircleNotFoundException
* @throws NoUserException
* @throws OwnerNotFoundException
*/
public function commandLineViewer(string $userId, bool $bypass = false) {
public function commandLineInitiator(string $userId, string $circleId = '', bool $bypass = false) {
if ($userId !== '') {
$currentUser = $this->createCurrentUserTypeUser($userId);
$this->setCurrentUser($currentUser);
} elseif ($bypass) {
$this->bypassCurrentUserCondition(true);
$this->setCurrentUser($this->createFederatedUserTypeUser($userId));
return;
}
if ($circleId !== '') {
$localCircle = $this->circleRequest->getCircle($circleId);
if ($this->configService->isLocalInstance($localCircle->getInstance())) {
// TODO: manage NO_OWNER circles
$this->setCurrentUser($localCircle->getOwner());
return;
}
}
if (!$bypass) {
throw new CircleNotFoundException(
'This Circle is not managed from this instance, please use --initiator'
);
}
$this->bypassCurrentUserCondition($bypass);
}
@ -269,54 +288,54 @@ class CurrentUserService {
list($userId, $level) = explode(',', $userId);
}
$currentUser = $this->createCurrentUserTypeUser($userId);
$federatedUser = $this->createFederatedUserTypeUser($userId);
$member = new Member();
$member->importFromIMember($currentUser)
->setLevel((int)$level);
$member->importFromIFederatedUser($federatedUser);
$member->setLevel((int)$level);
return $member;
}
/**
* @param CurrentUser $currentUser
* @param FederatedUser $federatedUser
*
* @throws CircleNotFoundException
*/
private function fillSingleCircleId(CurrentUser $currentUser): void {
if ($currentUser->getId() !== '') {
private function fillSingleCircleId(FederatedUser $federatedUser): void {
if ($federatedUser->getSingleId() !== '') {
return;
}
// only if currentUser is from LocalInstance
if ($this->configService->isLocalInstance($currentUser->getInstance())) {
$circle = $this->getSingleCircle($currentUser);
$currentUser->setId($circle->getId());
if ($this->configService->isLocalInstance($federatedUser->getInstance())) {
$circle = $this->getSingleCircle($federatedUser);
$federatedUser->setSingleId($circle->getId());
}
}
/**
* @param CurrentUser $currentUser
* @param FederatedUser $federatedUser
*
* @return Circle
* @throws CircleNotFoundException
*/
public function getSingleCircle(CurrentUser $currentUser): Circle {
public function getSingleCircle(FederatedUser $federatedUser): Circle {
try {
return $this->circleRequest->getViewerCircle($currentUser);
return $this->circleRequest->getInitiatorCircle($federatedUser);
} catch (CircleNotFoundException $e) {
$circle = new Circle();
$id = $this->token(Circle::ID_LENGTH);
$circle->setName('single:' . $currentUser->getUserId() . ':' . $id)
$circle->setName('single:' . $federatedUser->getUserId() . ':' . $id)
->setId($id)
->setConfig(Circle::CFG_SINGLE);
$this->circleRequest->save($circle);
$owner = new Member();
$owner->importFromIMember($currentUser)
->setLevel(Member::LEVEL_OWNER)
$owner->importFromIFederatedUser($federatedUser);
$owner->setLevel(Member::LEVEL_OWNER)
->setCircleId($id)
->setId($id)
->setCachedName($owner->getUserId())
@ -324,27 +343,26 @@ class CurrentUserService {
$this->memberRequest->save($owner);
}
return $this->circleRequest->getViewerCircle($currentUser);
return $this->circleRequest->getInitiatorCircle($federatedUser);
}
/**
* @param CurrentUser $currentUser
* @param FederatedUser $federatedUser
*
* @return Membership[]
*/
public function generateMemberships(CurrentUser $currentUser): array {
$circles = $this->circleRequest->getCircles(null, $currentUser);
public function generateMemberships(FederatedUser $federatedUser): array {
$circles = $this->circleRequest->getCircles(null, $federatedUser);
$memberships = [];
foreach ($circles as $circle) {
$viewer = $circle->getViewer();
if (!$viewer->isMember()) {
$initiator = $circle->getInitiator();
if (!$initiator->isMember()) {
continue;
}
$viewer = $circle->getViewer();
$memberships[] = new Membership(
$viewer->getId(), $circle->getId(), $currentUser->getId(), $viewer->getLevel()
$initiator->getId(), $circle->getId(), $federatedUser->getSingleId(), $initiator->getLevel()
);
// $newUser = new CurrentUser($circle->getId(), Member::TYPE_CIRCLE, '');
@ -356,22 +374,22 @@ class CurrentUserService {
/**
* @param CurrentUser|null $currentUser
* @param FederatedUser|null $federatedUser
*/
public function updateMemberships(?CurrentUser $currentUser = null) {
if (is_null($currentUser)) {
$currentUser = $this->getCurrentUser();
public function updateMemberships(?FederatedUser $federatedUser = null) {
if (is_null($federatedUser)) {
$federatedUser = $this->getCurrentUser();
} else {
$currentUser->setMemberships($this->membershipRequest->getMemberships($currentUser));
$federatedUser->setMemberships($this->membershipRequest->getMemberships($federatedUser));
}
if (is_null($currentUser)) {
if (is_null($federatedUser)) {
return;
}
$last = $this->generateMemberships($currentUser);
$last = $this->generateMemberships($federatedUser);
echo 'known: ' . json_encode($currentUser->getMemberships()) . "\n";
echo 'known: ' . json_encode($federatedUser->getMemberships()) . "\n";
echo 'last: ' . json_encode($last) . "\n";
//
@ -383,7 +401,7 @@ class CurrentUserService {
// }
//
// echo 'new member: ' . json_encode($viewer) . "\n";
//// $this->currentUserService->updateMembership($circle);
//// $this->federatedUserService->updateMembership($circle);
// }

View file

@ -151,7 +151,6 @@ class GSUpstreamService {
);
throw $e;
}
}

View file

@ -32,19 +32,25 @@ declare(strict_types=1);
namespace OCA\Circles\Service;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Logger;
use daita\MySmallPhpTools\Traits\TArrayTools;
use daita\MySmallPhpTools\Traits\TStringTools;
use Exception;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteEventException;
use OCA\Circles\Exceptions\ViewerNotFoundException;
use OCA\Circles\IMember;
use OCA\Circles\Model\CurrentUser;
use OCA\Circles\FederatedItems\MemberAdd;
use OCA\Circles\FederatedItems\MemberLevel;
use OCA\Circles\IFederatedUser;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\RemoteEvents\MemberAdd;
/**
@ -57,6 +63,7 @@ class MemberService {
use TArrayTools;
use TStringTools;
use TNC21Logger;
/** @var CircleRequest */
@ -65,11 +72,11 @@ class MemberService {
/** @var MemberRequest */
private $memberRequest;
/** @var CurrentUserService */
private $currentUserService;
/** @var FederatedUserService */
private $federatedUserService;
/** @var RemoteEventService */
private $remoteEventService;
/** @var FederatedEventService */
private $federatedEventService;
/**
@ -77,17 +84,18 @@ class MemberService {
*
* @param CircleRequest $circleRequest
* @param MemberRequest $memberRequest
* @param CurrentUserService $currentUserService
* @param RemoteEventService $remoteEventService
* @param FederatedUserService $federatedUserService
* @param FederatedEventService $federatedEventService
*/
public function __construct(
CircleRequest $circleRequest, MemberRequest $memberRequest, CurrentUserService $currentUserService,
RemoteEventService $remoteEventService
CircleRequest $circleRequest, MemberRequest $memberRequest,
FederatedUserService $federatedUserService,
FederatedEventService $federatedEventService
) {
$this->circleRequest = $circleRequest;
$this->memberRequest = $memberRequest;
$this->currentUserService = $currentUserService;
$this->remoteEventService = $remoteEventService;
$this->federatedUserService = $federatedUserService;
$this->federatedEventService = $federatedEventService;
}
//
@ -102,6 +110,34 @@ class MemberService {
// }
//
/**
* @param string $memberId
*
* @return Member
* @throws InitiatorNotFoundException
* @throws MemberLevelException
*/
public function getMember(string $memberId): Member {
$this->federatedUserService->mustHaveCurrentUser();
try {
$member = $this->memberRequest->getMember($memberId);
$circle = $this->circleRequest->getCircle(
$member->getCircleId(), $this->federatedUserService->getCurrentUser()
);
if (!$circle->getInitiator()->isMember()) {
throw new MemberLevelException();
}
return $member;
} catch (Exception $e) {
$this->e($e, ['id' => $memberId, 'initiator' => $this->federatedUserService->getCurrentUser()]);
throw new MemberLevelException('insufficient rights');
}
}
/**
* @param string $circleId
*
@ -114,49 +150,82 @@ class MemberService {
/**
* @param string $circleId
* @param IMember $member
* @param IFederatedUser $member
*
* @throws CircleNotFoundException
* @throws ViewerNotFoundException
* @throws OwnerNotFoundException
* @throws RemoteEventException
* @throws FederatedEventException
* @throws InitiatorNotFoundException
* @throws InitiatorNotConfirmedException
*/
public function addMember(string $circleId, IMember $member) {
$this->currentUserService->mustHaveCurrentUser();
$circle = $this->circleRequest->getCircle($circleId, $this->currentUserService->getCurrentUser());
public function addMember(string $circleId, IFederatedUser $member) {
$this->federatedUserService->mustHaveCurrentUser();
$circle = $this->circleRequest->getCircle($circleId, $this->federatedUserService->getCurrentUser());
if ($member instanceof CurrentUser) {
if ($member instanceof FederatedUser) {
$tmp = new Member();
$tmp->importFromIMember($member);
$tmp->importFromIFederatedUser($member);
$member = $tmp;
}
// $member->setId($this->token(Member::ID_LENGTH))
// ->setCircleId($circle->getId())
//
// $member = new Member();
// $member->importFromIMember($owner);
// $member->setId($this->token(Member::ID_LENGTH))
// ->setCircleId($circle->getId())
// ->setLevel(Member::LEVEL_OWNER)
// ->setStatus(Member::STATUS_MEMBER);
// $circle->setOwner($member);
//
$event = new RemoteEvent(MemberAdd::class);
$event = new FederatedEvent(MemberAdd::class);
$event->setCircle($circle);
$event->setMember($member);
$this->remoteEventService->newEvent($event);
// return $circle;
$this->federatedEventService->newEvent($event);
}
//
// // TODO: Use memberships to manage access level to a Circle !
// if ($circle->getViewer()->getLevel() < Member::LEVEL_MODERATOR) {
// throw new MemberLevelException('member have no rights to add a member to this circle');
// }
/**
* @param string $circleId
* @param string $memberId
* @param int $level
*
* @throws CircleNotFoundException
* @throws FederatedEventException
* @throws InitiatorNotConfirmedException
* @throws InitiatorNotFoundException
* @throws OwnerNotFoundException
* @throws \OCA\Circles\Exceptions\RemoteNotFoundException
* @throws \OCA\Circles\Exceptions\RemoteResourceNotFoundException
* @throws \OCA\Circles\Exceptions\UnknownRemoteException
* @throws \daita\MySmallPhpTools\Exceptions\RequestNetworkException
* @throws \daita\MySmallPhpTools\Exceptions\SignatoryException
* @throws MemberNotFoundException
*/
public function memberLevel(string $memberId, int $level): void {
$this->federatedUserService->mustHaveCurrentUser();
$member = $this->memberRequest->getMember($memberId, $this->federatedUserService->getCurrentUser());
echo json_encode($member, JSON_PRETTY_PRINT) . "\n";
$event = new FederatedEvent(MemberLevel::class);
$event->setCircle($member->getCircle());
$event->setMember($member);
$this->federatedEventService->newEvent($event);
}
/**
* @param string $levelString
*
* @return int
* @throws MemberLevelException
*/
public function parseLevelString(string $levelString): int {
$levelString = ucfirst(strtolower($levelString));
$level = array_search($levelString, Member::$DEF_LEVEL);
if (!$level) {
throw new MemberLevelException(
'Available levels: ' . implode(', ', array_values(Member::$DEF_LEVEL))
);
}
return (int)$level;
}
}

View file

@ -35,10 +35,15 @@ namespace OCA\Circles\Service;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Logger;
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\GlobalScaleDSyncException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteEventException;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\Model\Federated\FederatedEvent;
/**
@ -52,38 +57,39 @@ class RemoteDownstreamService {
use TNC21Logger;
// /** @var GlobalScaleService */
// private $globalScaleService;
//
// /** @var ConfigService */
// private $configService;
//
/** @var CircleRequest */
private $circleRequest;
/** @var RemoteEventService */
private $remoteEventService;
/** @var MemberRequest */
private $memberRequest;
/** @var FederatedEventService */
private $federatedEventService;
/** @var ConfigService */
private $configService;
/**
* RemoteDownstreamService constructor.
*
* @param CircleRequest $circleRequest
* @param RemoteEventService $remoteEventService
* @param MemberRequest $memberRequest
* @param FederatedEventService $federatedEventService
* @param ConfigService $configService
*/
public function __construct(
CircleRequest $circleRequest,
RemoteEventService $remoteEventService,
MemberRequest $memberRequest,
FederatedEventService $federatedEventService,
ConfigService $configService
) {
$this->setup('app', 'circles');
$this->circleRequest = $circleRequest;
$this->remoteEventService = $remoteEventService;
// $this->configService = $configService;
$this->memberRequest = $memberRequest;
$this->federatedEventService = $federatedEventService;
$this->configService = $configService;
}
@ -109,41 +115,58 @@ class RemoteDownstreamService {
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @throws RemoteEventException
* @throws FederatedEventException
* @throws InitiatorNotConfirmedException
* @throws OwnerNotFoundException
* @throws GlobalScaleDSyncException
* @throws FederatedEventDSyncException
*/
public function requestedEvent(RemoteEvent $event) {
// if ($event instanceof IRemoteEventMustBeLocal) {
// return true;
// }
public function requestedEvent(FederatedEvent $event): void {
try {
$gs = $this->federatedEventService->getFederatedItem($event, false);
} catch (FederatedEventException $e) {
$this->e($e);
throw $e;
}
// $gs = $this->remoteEventService->getRemoteEvent($event);
// if (!$this->remoteEventService->isLocalEvent($event)) {
// return;
if (!$this->configService->isLocalInstance($event->getCircle()->getInstance())) {
throw new FederatedEventException('Circle is not from this instance');
}
$this->federatedEventService->confirmInitiator($event, false);
try {
$this->confirmContent($event);
} catch (Exception $e) {
throw new FederatedEventDSyncException();
}
$gs->verify($event);
// async.
// if (!$event->isAsync()) {
// $gs->manage($event);
// }
//
// $this->initBroadcast($event);
// } else {
// $this->remoteUpstreamService->confirmEvent($event);
// }
//
// $gs->verify($event);
//
// if (!$event->isAsync()) {
// $gs->manage($event);
// }
// $this->globalScaleService->asyncBroadcast($event);
}
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @return array
*/
public function incomingEvent(RemoteEvent $event): array {
public function incomingEvent(FederatedEvent $event): array {
$result = [];
try {
$gs = $this->remoteEventService->getRemoteEvent($event);
$this->confirmCircle($event);
$gs = $this->federatedEventService->getFederatedItem($event);
$this->confirmOriginEvent($event);
$this->confirmContent($event);
$gs->manage($event);
} catch (Exception $e) {
@ -155,24 +178,38 @@ class RemoteDownstreamService {
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @throws RemoteEventException
* @throws FederatedEventDSyncException
* @throws OwnerNotFoundException
*/
private function confirmCircle(RemoteEvent $event): void {
if ($event->canBypass(RemoteEvent::BYPASS_LOCALCIRCLECHECK) || $this->verifyCircle($event)) {
private function confirmContent(FederatedEvent $event): void {
$this->confirmCircle($event);
$this->confirmMember($event);
}
/**
* @param FederatedEvent $event
*
* @throws OwnerNotFoundException
* @throws FederatedEventDSyncException
*/
private function confirmCircle(FederatedEvent $event): void {
if ($event->canBypass(FederatedEvent::BYPASS_LOCALCIRCLECHECK) || $this->verifyCircle($event)) {
return;
}
throw new RemoteEventException('could not verify circle');
throw new FederatedEventDSyncException('Could not verify Circle');
}
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @return bool
* @throws OwnerNotFoundException
*/
private function verifyCircle(RemoteEvent $event): bool {
private function verifyCircle(FederatedEvent $event): bool {
$circle = $event->getCircle();
try {
$localCircle = $this->circleRequest->getCircle($circle->getId());
@ -180,20 +217,54 @@ class RemoteDownstreamService {
return false;
}
return ($localCircle->compareWith($circle));
if (!$localCircle->compareWith($circle)) {
return false;
}
}
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
*
* @throws RemoteEventException
* @throws FederatedEventDSyncException
*/
private function confirmMember(FederatedEvent $event): void {
if (!$event->hasMember() || $this->verifyMember($event)) {
return;
}
throw new FederatedEventDSyncException('Could not verify Member');
}
/**
* @param FederatedEvent $event
*
* @return bool
*/
private function verifyMember(FederatedEvent $event): bool {
$member = $event->getMember();
try {
$localMember = $this->memberRequest->getMember($member->getId());
} catch (MemberNotFoundException $e) {
return false;
}
if (!$localMember->compareWith($member)) {
return false;
}
}
/**
* @param FederatedEvent $event
*
* @throws FederatedEventException
* @throws OwnerNotFoundException
*/
private function confirmOriginEvent(RemoteEvent $event): void {
private function confirmOriginEvent(FederatedEvent $event): void {
if ($event->getIncomingOrigin() !== $event->getCircle()->getInstance()) {
$this->debug('invalid origin', ['event' => $event]);
throw new RemoteEventException('invalid origin');
throw new FederatedEventException('invalid origin');
}
}

View file

@ -39,6 +39,7 @@ use daita\MySmallPhpTools\Exceptions\SignatureException;
use daita\MySmallPhpTools\Exceptions\WellKnownLinkNotFoundException;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21Request;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21Signatory;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21SignedRequest;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Convert;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21LocalSignatory;
@ -53,7 +54,7 @@ use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\RemoteUidException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCP\IURLGenerator;
@ -163,18 +164,14 @@ class RemoteService extends NC21Signature {
* @throws UnknownRemoteException
*/
public function getCircles(string $instance): array {
$circles = $this->requestRemoteInstance($instance, RemoteInstance::CIRCLES);
$circles = $this->resultRequestRemoteInstance($instance, RemoteInstance::CIRCLES);
return $this->convertArray($circles, Circle::class);
}
/**
* Send a request to a remote instance, based on:
* - instance: address as saved in database,
* - item: the item to request (incoming, event, ...)
* - type: GET, POST
* - data: Serializable to be send if needed
* shortcut to requestRemoteInstance that return result if available, or exception.
*
* @param string $instance
* @param string $item
@ -188,12 +185,45 @@ class RemoteService extends NC21Signature {
* @throws SignatoryException
* @throws UnknownRemoteException
*/
public function requestRemoteInstance(
public function resultRequestRemoteInstance(
string $instance,
string $item,
int $type = Request::TYPE_GET,
?JsonSerializable $object = null
): array {
$signedRequest = $this->requestRemoteInstance($instance, $item, $type, $object);
if (!$signedRequest->getOutgoingRequest()->hasResult()) {
throw new RequestNetworkException();
}
return $signedRequest->getOutgoingRequest()->getResult()->getAsArray();
}
/**
* Send a request to a remote instance, based on:
* - instance: address as saved in database,
* - item: the item to request (incoming, event, ...)
* - type: GET, POST
* - data: Serializable to be send if needed
*
* @param string $instance
* @param string $item
* @param int $type
* @param JsonSerializable|null $object
*
* @return NC21SignedRequest
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
*/
public function requestRemoteInstance(
string $instance,
string $item,
int $type = Request::TYPE_GET,
?JsonSerializable $object = null
): NC21SignedRequest {
$request = new NC21Request('', $type);
if ($this->configService->isLocalInstance($instance)) {
@ -214,7 +244,6 @@ class RemoteService extends NC21Signature {
// $request->setInstance($instance);
// }
if (!is_null($object)) {
$request->setDataSerialize($object);
}
@ -222,9 +251,9 @@ class RemoteService extends NC21Signature {
$app = $this->getAppSignatory();
// $app->setAlgorithm(NC21Signatory::SHA512);
$signedRequest = $this->signOutgoingRequest($request, $app);
$this->doRequest($signedRequest->getOutgoingRequest());
$this->doRequest($signedRequest->getOutgoingRequest(), false);
return $signedRequest->getOutgoingRequest()->getResult()->getAsArray();
return $signedRequest;
}

View file

@ -32,33 +32,26 @@ declare(strict_types=1);
namespace OCA\Circles\Service;
use daita\MySmallPhpTools\Exceptions\RequestContentException;
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
use daita\MySmallPhpTools\Exceptions\RequestResultNotJsonException;
use daita\MySmallPhpTools\Exceptions\RequestResultSizeException;
use daita\MySmallPhpTools\Exceptions\RequestServerException;
use daita\MySmallPhpTools\Exceptions\SignatoryException;
use daita\MySmallPhpTools\Exceptions\SignatureException;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21Request;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Model\SimpleDataStore;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Request;
use Exception;
use OCA\Circles\Db\DeprecatedCirclesRequest;
use OCA\Circles\Db\DeprecatedMembersRequest;
use OCA\Circles\Db\RemoteWrapperRequest;
use OCA\Circles\Exceptions\GSStatusException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\GlobalScale\CircleStatus;
use OCA\Circles\Model\DeprecatedCircle;
use OCA\Circles\Model\GlobalScale\GSEvent;
use OCA\Circles\Model\GlobalScale\GSWrapper;
use OCA\Circles\Model\Remote\RemoteEvent;
use OCA\Circles\Model\Remote\RemoteInstance;
use OCA\Circles\Model\Remote\RemoteWrapper;
use OCP\IURLGenerator;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCA\Circles\Model\Federated\RemoteWrapper;
use OCP\AppFramework\Http;
use OCP\IL10N;
/**
@ -72,47 +65,44 @@ class RemoteUpstreamService {
use TNC21Request;
/** @var IURLGenerator */
private $urlGenerator;
private $l10n;
/** @var RemoteWrapperRequest */
private $remoteWrapperRequest;
/** @var DeprecatedCirclesRequest */
private $circlesRequest;
/** @var DeprecatedMembersRequest */
private $membersRequest;
/** @var RemoteService */
private $remoteService;
/** @var RemoteEventService */
private $remoteEventService;
/** @var FederatedEventService */
private $federatedEventService;
/** @var ConfigService */
private $configService;
public function __construct(
IURLGenerator $urlGenerator,
IL10N $l10n,
RemoteWrapperRequest $remoteWrapperRequest,
DeprecatedCirclesRequest $circlesRequest,
DeprecatedMembersRequest $membersRequest,
RemoteService $remoteService,
RemoteEventService $remoteEventService,
ConfigService $configService
) {
$this->urlGenerator = $urlGenerator;
$this->l10n = $l10n;
$this->remoteWrapperRequest = $remoteWrapperRequest;
$this->circlesRequest = $circlesRequest;
$this->membersRequest = $membersRequest;
$this->remoteService = $remoteService;
$this->remoteEventService = $remoteEventService;
$this->configService = $configService;
}
/**
* @param string $token
*
* @return RemoteWrapper[]
*/
public function getEventsByToken(string $token): array {
return $this->remoteWrapperRequest->getByToken($token);
}
/**
* @param RemoteWrapper $wrapper
*/
@ -136,7 +126,7 @@ class RemoteUpstreamService {
/**
* @param RemoteEvent $event
* @param FederatedEvent $event
* @param string $instance
*
* @throws RequestNetworkException
@ -146,7 +136,7 @@ class RemoteUpstreamService {
* @throws RemoteResourceNotFoundException
* @throws UnknownRemoteException
*/
public function broadcastEvent(RemoteEvent $event, string $instance): void {
public function broadcastEvent(FederatedEvent $event, string $instance): void {
// if ($this->configService->isLocalInstance($instance)) {
// $request = new NC21Request('', Request::TYPE_POST);
// $this->configService->configureRequest($request, 'circles.RemoteWrapper.broadcast');
@ -159,7 +149,7 @@ class RemoteUpstreamService {
// $request->setDataSerialize($event);
$data = $this->remoteService->requestRemoteInstance(
$data = $this->remoteService->resultRequestRemoteInstance(
$instance,
RemoteInstance::INCOMING,
Request::TYPE_POST,
@ -171,184 +161,254 @@ class RemoteUpstreamService {
/**
* @param string $token
* @param FederatedEvent $event
*
* @return RemoteWrapper[]
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws OwnerNotFoundException
* @throws RequestNetworkException
* @throws FederatedEventException
*/
public function getEventsByToken(string $token): array {
return $this->remoteWrapperRequest->getByToken($token);
public function confirmEvent(FederatedEvent $event): string {
$data = $this->remoteService->requestRemoteInstance(
$event->getCircle()->getInstance(),
RemoteInstance::EVENT,
Request::TYPE_POST,
$event
);
// TODO: check what is happening if website is down...
if (!$data->getOutgoingRequest()->hasResult()
|| $data->getOutgoingRequest()->getResult()->hasException()) {
throw new RequestNetworkException();
}
$result = $data->getOutgoingRequest()->getResult();
$data = new SimpleDataStore($result->getAsArray());
$message = $this->l10n->t($data->g('message'), $data->gArray('params'));
if ($result->getStatusCode() === Http::STATUS_OK && $data->gBool('status')) {
return $message;
}
throw new FederatedEventException($message);
//
// echo '___1' . json_encode($result) . "\n";
//
// if ($result->hasException()) {
// $fails = $data->getOutgoingRequest()->getAllResults();
// foreach ($fails as $fail) {
//
// if ($fail->getStatusCode() === Http::STATUS_BAD_REQUEST) {
// throw new RemoteEventException('Event is not valid');
// }
// }
//
// throw new RequestNetworkException();
// }
// $path = $this->urlGenerator->linkToRoute('circles.RemoteWrapper.event');
//
// $request = new NC21Request($path, Request::TYPE_POST);
// $this->configService->configureRequest($request);
// $request->basedOnUrl($owner->getInstance());
//
// $request->setDataSerialize($event);
//
// $result = $this->retrieveJson($request);
// $this->debug('confirming RemoteEvent', ['event' => $event, 'request' => $request]);
////
//// if ($this->getInt('status', $result) === 0) {
//// throw new GlobalScaleEventException($this->get('error', $result));
//// }
//
//// $updatedData = $this->getArray('event', $result);
//// $this->miscService->log('updatedEvent: ' . json_encode($updatedData), 0);
//// if (!empty($updatedData)) {
//// $updated = new GSEvent();
//// try {
//// $updated->import($updatedData);
//// $event = $updated;
//// } catch (Exception $e) {
//// }
//// }
}
//
//
//
//
//
/**
* @param array $sync
*
* @throws GSStatusException
*/
public function synchronize(array $sync) {
$this->configService->getGSStatus();
$this->synchronizeCircles($sync);
$this->removeDeprecatedCircles();
$this->removeDeprecatedEvents();
}
// /**
// * @param array $sync
// *
// * @throws GSStatusException
// */
// public function synchronize(array $sync) {
// $this->configService->getGSStatus();
//
// $this->synchronizeCircles($sync);
// $this->removeDeprecatedCircles();
// $this->removeDeprecatedEvents();
// }
/**
* @param array $circles
*/
public function synchronizeCircles(array $circles): void {
$event = new GSEvent(GSEvent::GLOBAL_SYNC, true);
$event->setSource($this->configService->getLocalInstance());
$event->setData(new SimpleDataStore($circles));
foreach ($this->remoteEventService->getInstances() as $instance) {
try {
$this->broadcastEvent($event, $instance);
} catch (RequestContentException | RequestNetworkException | RequestResultSizeException | RequestServerException | RequestResultNotJsonException $e) {
}
}
}
/**
*
*/
private function removeDeprecatedCircles() {
$knownCircles = $this->circlesRequest->forceGetCircles();
foreach ($knownCircles as $knownItem) {
if ($knownItem->getOwner()
->getInstance() === '') {
continue;
}
try {
$this->checkCircle($knownItem);
} catch (GSStatusException $e) {
}
}
}
/**
* @param DeprecatedCircle $circle
*
* @throws GSStatusException
*/
private function checkCircle(DeprecatedCircle $circle): void {
$status = $this->confirmCircleStatus($circle);
if (!$status) {
$this->circlesRequest->destroyCircle($circle->getUniqueId());
$this->membersRequest->removeAllFromCircle($circle->getUniqueId());
}
}
/**
* @param DeprecatedCircle $circle
*
* @return bool
* @throws GSStatusException
*/
public function confirmCircleStatus(DeprecatedCircle $circle): bool {
$event = new GSEvent(GSEvent::CIRCLE_STATUS, true);
$event->setSource($this->configService->getLocalInstance());
$event->setDeprecatedCircle($circle);
$this->signEvent($event);
$path = $this->urlGenerator->linkToRoute('circles.RemoteWrapper.status');
$request = new NC21Request($path, Request::TYPE_POST);
$this->configService->configureRequest($request);
$request->setDataSerialize($event);
$requestIssue = false;
$notFound = false;
$foundWithNoOwner = false;
foreach ($this->remoteEventService->getInstances() as $instance) {
$request->setHost($instance);
try {
$result = $this->retrieveJson($request);
if ($this->getInt('status', $result, 0) !== 1) {
throw new RequestContentException('result status is not good');
}
$status = $this->getInt('success.data.status', $result);
// if error, we assume the circle might still exist.
if ($status === CircleStatus::STATUS_ERROR) {
return true;
}
if ($status === CircleStatus::STATUS_OK) {
return true;
}
// TODO: check the data.supposedOwner entry.
if ($status === CircleStatus::STATUS_NOT_OWNER) {
$foundWithNoOwner = true;
}
if ($status === CircleStatus::STATUS_NOT_FOUND) {
$notFound = true;
}
} catch (RequestContentException
| RequestNetworkException
| RequestResultNotJsonException
| RequestResultSizeException
| RequestServerException $e) {
$requestIssue = true;
// TODO: log instances that have network issue, after too many tries (7d), remove this circle.
continue;
}
}
// if no request issue, we can imagine that the instance that owns the circle is down.
// We'll wait for more information (cf request exceptions management);
if ($requestIssue) {
return true;
}
// circle were not found in any other instances, we can easily says that the circle does not exists anymore
if ($notFound && !$foundWithNoOwner) {
return false;
}
// circle were found everywhere but with no owner on every instance. we need to assign a new owner.
// This should be done by checking admin rights. if no admin rights, let's assume that circle should be removed.
if (!$notFound && $foundWithNoOwner) {
// TODO: assign a new owner and check that when changing owner, we do check that the destination instance is updated FOR SURE!
return true;
}
// some instances returned notFound, some returned circle with no owner. let's assume the circle is deprecated.
return false;
}
/**
* @throws GSStatusException
*/
public function syncEvents() {
}
/**
*
*/
private function removeDeprecatedEvents() {
// $this->deprecatedEvents();
}
// /**
// * @param array $circles
// */
// public function synchronizeCircles(array $circles): void {
// $event = new GSEvent(GSEvent::GLOBAL_SYNC, true);
// $event->setSource($this->configService->getLocalInstance());
// $event->setData(new SimpleDataStore($circles));
//
// foreach ($this->federatedEventService->getInstances() as $instance) {
// try {
// $this->broadcastEvent($event, $instance);
// } catch (RequestContentException | RequestNetworkException | RequestResultSizeException | RequestServerException | RequestResultNotJsonException $e) {
// }
// }
// }
//
//
// /**
// *
// */
// private function removeDeprecatedCircles() {
// $knownCircles = $this->circlesRequest->forceGetCircles();
// foreach ($knownCircles as $knownItem) {
// if ($knownItem->getOwner()
// ->getInstance() === '') {
// continue;
// }
//
// try {
// $this->checkCircle($knownItem);
// } catch (GSStatusException $e) {
// }
// }
// }
//
//
// /**
// * @param DeprecatedCircle $circle
// *
// * @throws GSStatusException
// */
// private function checkCircle(DeprecatedCircle $circle): void {
// $status = $this->confirmCircleStatus($circle);
//
// if (!$status) {
// $this->circlesRequest->destroyCircle($circle->getUniqueId());
// $this->membersRequest->removeAllFromCircle($circle->getUniqueId());
// }
// }
//
//
// /**
// * @param DeprecatedCircle $circle
// *
// * @return bool
// * @throws GSStatusException
// */
// public function confirmCircleStatus(DeprecatedCircle $circle): bool {
// $event = new GSEvent(GSEvent::CIRCLE_STATUS, true);
// $event->setSource($this->configService->getLocalInstance());
// $event->setDeprecatedCircle($circle);
//
// $this->signEvent($event);
//
// $path = $this->urlGenerator->linkToRoute('circles.RemoteWrapper.status');
// $request = new NC21Request($path, Request::TYPE_POST);
// $this->configService->configureRequest($request);
// $request->setDataSerialize($event);
//
// $requestIssue = false;
// $notFound = false;
// $foundWithNoOwner = false;
// foreach ($this->federatedEventService->getInstances() as $instance) {
// $request->setHost($instance);
//
// try {
// $result = $this->retrieveJson($request);
// if ($this->getInt('status', $result, 0) !== 1) {
// throw new RequestContentException('result status is not good');
// }
//
// $status = $this->getInt('success.data.status', $result);
//
// // if error, we assume the circle might still exist.
// if ($status === CircleStatus::STATUS_ERROR) {
// return true;
// }
//
// if ($status === CircleStatus::STATUS_OK) {
// return true;
// }
//
// // TODO: check the data.supposedOwner entry.
// if ($status === CircleStatus::STATUS_NOT_OWNER) {
// $foundWithNoOwner = true;
// }
//
// if ($status === CircleStatus::STATUS_NOT_FOUND) {
// $notFound = true;
// }
//
// } catch (RequestContentException
// | RequestNetworkException
// | RequestResultNotJsonException
// | RequestResultSizeException
// | RequestServerException $e) {
// $requestIssue = true;
// // TODO: log instances that have network issue, after too many tries (7d), remove this circle.
// continue;
// }
// }
//
// // if no request issue, we can imagine that the instance that owns the circle is down.
// // We'll wait for more information (cf request exceptions management);
// if ($requestIssue) {
// return true;
// }
//
// // circle were not found in any other instances, we can easily says that the circle does not exists anymore
// if ($notFound && !$foundWithNoOwner) {
// return false;
// }
//
// // circle were found everywhere but with no owner on every instance. we need to assign a new owner.
// // This should be done by checking admin rights. if no admin rights, let's assume that circle should be removed.
// if (!$notFound && $foundWithNoOwner) {
// // TODO: assign a new owner and check that when changing owner, we do check that the destination instance is updated FOR SURE!
// return true;
// }
//
// // some instances returned notFound, some returned circle with no owner. let's assume the circle is deprecated.
// return false;
// }
//
// /**
// * @throws GSStatusException
// */
// public function syncEvents() {
//
// }
//
// /**
// *
// */
// private function removeDeprecatedEvents() {
//// $this->deprecatedEvents();
//
// }
}