migrate therinaldos.com data
Build & Deploy to DigitalOcean Space / build (push) Failing after 2m38s

This commit is contained in:
2024-05-05 15:50:45 -04:00
commit ef1ff240d4
23182 changed files with 3801898 additions and 0 deletions
@@ -0,0 +1,196 @@
<?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\FederatedItems;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\PermissionService;
use OCA\Circles\Tools\Traits\TDeserialize;
/**
* Class CircleConfig
*
* @package OCA\Circles\FederatedItems
*/
class CircleConfig implements
IFederatedItem {
use TDeserialize;
/** @var CircleRequest */
private $circleRequest;
/** @var PermissionService */
private $permissionService;
/** @var ConfigService */
private $configService;
/**
* CircleConfig constructor.
*
* @param CircleRequest $circleRequest
* @param PermissionService $permissionService
* @param ConfigService $configService
*/
public function __construct(
CircleRequest $circleRequest,
PermissionService $permissionService,
ConfigService $configService
) {
$this->circleRequest = $circleRequest;
$this->permissionService = $permissionService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemException
* @throws RequestBuilderException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$config = $event->getParams()->gInt('config');
$initiatorHelper = new MemberHelper($circle->getInitiator());
$initiatorHelper->mustBeAdmin();
$listing = Circle::$DEF_CFG_CORE_FILTER;
if (!$circle->isConfig(Circle::CFG_SYSTEM)) {
$listing = array_merge($listing, Circle::$DEF_CFG_SYSTEM_FILTER);
}
// filtering config values when not using Super Session
if (!$event->getParams()->gBool('superSession')) {
if ($circle->isConfig(Circle::CFG_APP)) {
$config |= Circle::CFG_APP;
} else {
$config &= ~Circle::CFG_APP;
}
}
$confirmed = true;
foreach ($listing as $item) {
if ($circle->isConfig($item, $config)) {
$confirmed = false;
}
}
if ($circle->isConfig(Circle::CFG_LOCAL, $config)
&& !$circle->isConfig(Circle::CFG_LOCAL)) {
$config -= Circle::CFG_LOCAL;
}
if (!$circle->isConfig(Circle::CFG_LOCAL, $config)
&& $circle->isConfig(Circle::CFG_LOCAL)) {
$config += Circle::CFG_LOCAL;
}
if (!$circle->isConfig(Circle::CFG_OPEN, $config)
&& $circle->isConfig(Circle::CFG_OPEN)
&& $circle->isConfig(Circle::CFG_REQUEST, $config)
) {
$config -= Circle::CFG_REQUEST;
}
if ($circle->isConfig(Circle::CFG_REQUEST, $config)
&& !$circle->isConfig(Circle::CFG_REQUEST)
&& !$circle->isConfig(Circle::CFG_OPEN, $config)) {
$config += Circle::CFG_OPEN;
}
if (!$circle->isConfig(Circle::CFG_ROOT, $config)
&& $circle->isConfig(Circle::CFG_ROOT)
&& $circle->isConfig(Circle::CFG_FEDERATED, $config)) {
$config -= Circle::CFG_FEDERATED;
// TODO: Broadcast message to other instances about loosing federated tag.
}
if ($circle->isConfig(Circle::CFG_FEDERATED, $config)
&& !$circle->isConfig(Circle::CFG_FEDERATED)
&& !$circle->isConfig(Circle::CFG_ROOT, $config)) {
$config += Circle::CFG_ROOT;
// TODO: Check locally that circle is not a member of another circle.
// TODO in that case, remove the membership (and update the memberships)
$event->getData()->sBool('_broadcastAsFederated', true);
}
if (!$confirmed || $config > Circle::$DEF_CFG_MAX) {
throw new FederatedItemBadRequestException('Configuration value is not valid');
}
$new = clone $circle;
$new->setConfig($config);
$this->permissionService->confirmAllowedCircleTypes($new, $circle);
$event->getData()->sInt('config', $new->getConfig());
$event->setOutcome($this->serialize($new));
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
$circle = clone $event->getCircle();
$config = $event->getData()->gInt('config');
$circle->setConfig($config);
// TODO: Check locally that circle is not un-federated during the process
// TODO: if the circle is managed remotely, remove the circle locally
// TODO: if the circle is managed locally, remove non-local users
// TODO: Check locally that circle is not federated during the process
// TODO: sync if it is to broadcast to Trusted RemoteInstance
$this->circleRequest->updateConfig($circle);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,160 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemCircleCheckNotRequired;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMustBeInitializedLocally;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\MembershipService;
/**
* Class CircleCreate
*
* @package OCA\Circles\FederatedItems
*/
class CircleCreate implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemCircleCheckNotRequired,
IFederatedItemMustBeInitializedLocally {
use TDeserialize;
/** @var CircleRequest */
private $circleRequest;
/** @var MemberRequest */
private $memberRequest;
/** @var CircleService */
private $circleService;
/** @var MembershipService */
private $membershipService;
/** @var EventService */
private $eventService;
/**
* CircleCreate constructor.
*
* @param CircleRequest $circleRequest
* @param MemberRequest $memberRequest
* @param CircleService $circleService
* @param MembershipService $membershipService
* @param EventService $eventService
*/
public function __construct(
CircleRequest $circleRequest,
MemberRequest $memberRequest,
CircleService $circleService,
MembershipService $membershipService,
EventService $eventService
) {
$this->circleRequest = $circleRequest;
$this->memberRequest = $memberRequest;
$this->circleService = $circleService;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$event->setOutcome($this->serialize($circle));
}
/**
* @param FederatedEvent $event
*
* @throws FederatedEventDSyncException
* @throws InvalidIdException
* @throws RequestBuilderException
*/
public function manage(FederatedEvent $event): void {
$circle = $event->getCircle();
$owner = $circle->getOwner();
try {
$this->circleRequest->getCircle($circle->getSingleId());
throw new FederatedEventDSyncException('Circle already exist');
} catch (CircleNotFoundException $e) {
}
$this->circleService->confirmName($circle);
try {
$this->memberRequest->getMemberById($owner->getId());
throw new FederatedEventDSyncException('Owner already exist');
} catch (MemberNotFoundException $e) {
}
if ($owner->hasInvitedBy()) {
$owner->setNoteObj('invitedBy', $owner->getInvitedBy());
}
$this->circleRequest->save($circle);
$this->memberRequest->save($owner);
$this->membershipService->onUpdate($owner->getSingleId());
$this->membershipService->updatePopulation($circle);
$this->eventService->circleCreating($event);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->circleCreated($event, $results);
}
}
@@ -0,0 +1,143 @@
<?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\FederatedItems;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberEmpty;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\MembershipService;
use OCA\Circles\StatusCode;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Tools\Traits\TStringTools;
/**
* Class CircleDestroy
*
* @package OCA\Circles\FederatedItems
*/
class CircleDestroy implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemAsyncProcess,
IFederatedItemMemberEmpty {
use TStringTools;
use TDeserialize;
/** @var CircleRequest */
private $circleRequest;
/** @var MemberRequest */
private $memberRequest;
private $eventService;
/** @var MembershipService */
private $membershipService;
/**
* CircleDestroy constructor.
*
* @param CircleRequest $circleRequest
* @param MemberRequest $memberRequest
* @param EventService $eventService
* @param MembershipService $membershipService
*/
public function __construct(
CircleRequest $circleRequest, MemberRequest $memberRequest, EventService $eventService,
MembershipService $membershipService
) {
$this->circleRequest = $circleRequest;
$this->memberRequest = $memberRequest;
$this->eventService = $eventService;
$this->membershipService = $membershipService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemBadRequestException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
if ($circle->isConfig(Circle::CFG_APP)) {
throw new FederatedItemBadRequestException(
StatusCode::$CIRCLE_DESTROY[120],
120
);
}
$initiator = $circle->getInitiator();
$initiatorHelper = new MemberHelper($initiator);
$initiatorHelper->mustBeOwner();
$event->setOutcome($this->serialize($circle));
}
/**
* @param FederatedEvent $event
*
* @throws RequestBuilderException
*/
public function manage(FederatedEvent $event): void {
$circle = $event->getCircle();
$this->eventService->circleDestroying($event);
$this->circleRequest->delete($circle);
$this->memberRequest->deleteAllFromCircle($circle);
$this->membershipService->onUpdate($circle->getSingleId());
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->circleDestroyed($event, $results);
}
}
@@ -0,0 +1,156 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNameTooShortException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\EventService;
/**
* Class CircleEdit
*
* @package OCA\Circles\FederatedItems
*/
class CircleEdit implements IFederatedItem {
use TDeserialize;
/** @var CircleRequest */
private $circleRequest;
/** @var MemberRequest */
private $memberRequest;
/** @var CircleService */
private $circleService;
/** @var EventService */
private $eventService;
/**
* CircleEdit constructor.
*
* @param CircleRequest $circleRequest
* @param MemberRequest $memberRequest
* @param CircleService $circleService
* @param EventService $eventService
*/
public function __construct(
CircleRequest $circleRequest,
MemberRequest $memberRequest,
CircleService $circleService,
EventService $eventService
) {
$this->circleRequest = $circleRequest;
$this->memberRequest = $memberRequest;
$this->circleService = $circleService;
$this->eventService = $eventService;
}
/**
* @param FederatedEvent $event
*
* @throws RequestBuilderException
* @throws CircleNameTooShortException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$initiatorHelper = new MemberHelper($circle->getInitiator());
$initiatorHelper->mustBeOwner();
$data = $event->getParams();
$new = clone $circle;
if ($data->hasKey('name')) {
$new->setName($this->circleService->cleanCircleName($data->g('name')));
if (strlen($new->getName()) < 3) {
throw new CircleNameTooShortException('Circle name is too short');
}
$event->getData()->s('name', $new->getName());
}
if ($data->hasKey('description')) {
$new->setDescription($data->g('description'));
$event->getData()->s('description', $new->getDescription());
}
$this->circleService->confirmName($new);
$event->setOutcome($this->serialize($new));
}
/**
* @param FederatedEvent $event
*
* @throws RequestBuilderException
*/
public function manage(FederatedEvent $event): void {
$circle = clone $event->getCircle();
$data = $event->getData();
// TODO: verify that event->GetCircle() is updated by the instance that owns the Circle so we can
// use it as a thrustable base
if ($data->hasKey('name')) {
$circle->setName($data->g('name'));
}
$this->circleService->confirmName($circle);
if ($data->hasKey('description')) {
$circle->setDescription($data->g('description'));
}
$this->circleRequest->edit($circle);
$this->memberRequest->updateDisplayName($circle->getSingleId(), $circle->getDisplayName());
$this->eventService->circleEditing($event);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->circleEdited($event, $results);
}
}
@@ -0,0 +1,320 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Tools\Traits\TNCLogger;
use OCA\Circles\Tools\Traits\TStringTools;
use Exception;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\MembersLimitException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemInitiatorMembershipNotRequired;
use OCA\Circles\IFederatedItemMemberCheckNotRequired;
use OCA\Circles\IFederatedItemMemberOptional;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\ManagedModel;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use OCA\Circles\Service\MembershipService;
use OCA\Circles\StatusCode;
use OCP\IUserManager;
/**
* Class CircleJoin
*
* @package OCA\Circles\GlobalScale
*/
class CircleJoin implements
IFederatedItem,
IFederatedItemInitiatorMembershipNotRequired,
IFederatedItemAsyncProcess,
IFederatedItemHighSeverity,
IFederatedItemMemberCheckNotRequired,
IFederatedItemMemberOptional {
use TStringTools;
use TNCLogger;
use TDeserialize;
/** @var IUserManager */
private $userManager;
/** @var MemberRequest */
private $memberRequest;
/** @var FederatedUserService */
private $federatedUserService;
/** @var CircleService */
private $circleService;
/** @var MemberService */
private $memberService;
/** @var MembershipService */
private $membershipService;
/** @var EventService */
private $eventService;
/** @var ConfigService */
private $configService;
/**
* CircleJoin constructor.
*
* @param IUserManager $userManager
* @param MemberRequest $memberRequest
* @param FederatedUserService $federatedUserService
* @param CircleService $circleService
* @param MembershipService $membershipService
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
IUserManager $userManager,
MemberRequest $memberRequest,
FederatedUserService $federatedUserService,
CircleService $circleService,
MemberService $memberService,
MembershipService $membershipService,
EventService $eventService,
ConfigService $configService
) {
$this->userManager = $userManager;
$this->memberRequest = $memberRequest;
$this->federatedUserService = $federatedUserService;
$this->circleService = $circleService;
$this->memberService = $memberService;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemBadRequestException
* @throws MembersLimitException
* @throws RequestBuilderException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$initiator = $circle->getInitiator();
$member = new Member();
$member->importFromIFederatedUser($initiator);
$member->setCircleId($circle->getSingleId());
if ($initiator->hasInvitedBy()) {
$member->setInvitedBy($initiator->getInvitedBy());
}
$this->manageMemberStatus($circle, $member);
$this->circleService->confirmCircleNotFull($circle);
$event->setMember($member)
->setOutcome($this->serialize($member));
return;
//
//
// $federatedId = $member->getUserId() . '@' . $member->getInstance();
// try {
// $federatedUser =
// $this->federatedUserService->getFederatedUser($federatedId, $member->getUserType());
// throw new MemberNotFoundException(
// ucfirst(Member::$DEF_TYPE[$member->getUserType()]) . ' \'%s\' not found',
// ['member' => $member->getUserId() . '@' . $member->getInstance()]
// );
// }
// $member->importFromIFederatedUser($federatedUser);
//
// try {
// $knownMember = $this->memberRequest->searchMember($member);
// // TODO: maybe member is requesting access
// throw new MemberAlreadyExistsException(
// ucfirst(Member::$DEF_TYPE[$member->getUserType()]) . ' %s is already a member',
// ['member' => $member->getUserId() . '@' . $member->getInstance()]
// );
// } catch (MemberNotFoundException $e) {
// }
// $member->setId($this->uuid(ManagedModel::ID_LENGTH));
//
// // TODO: check Config on Circle to know if we set Level to 1 or just send an invitation
// $member->setLevel(Member::LEVEL_MEMBER);
// $member->setStatus(Member::STATUS_MEMBER);
// $event->setDataOutcome(['member' => $member]);
//
// // TODO: Managing cached name
// // $member->setCachedName($eventMember->getCachedName());
// $this->circleService->confirmCircleNotFull($circle);
//
// // TODO: check if it is a member or a mail or a circle and fix the returned message
//
// return;
// $member = $this->membersRequest->getFreshNewMember(
// $circle->getUniqueId(), $ident, $eventMember->getType(), $eventMember->getInstance()
// );
// $member->hasToBeInviteAble()
//
// $this->membersService->addMemberBasedOnItsType($circle, $member);
//
// $password = '';
// $sendPasswordByMail = false;
// if ($this->configService->enforcePasswordProtection($circle)) {
// if ($circle->getSetting('password_single_enabled') === 'true') {
// $password = $circle->getPasswordSingle();
// } else {
// $sendPasswordByMail = true;
// $password = $this->miscService->token(15);
// }
// }
//
// $event->setData(
// new SimpleDataStore(
// [
// 'password' => $password,
// 'passwordByMail' => $sendPasswordByMail
// ]
// )
// );
}
/**
* @param FederatedEvent $event
*
* @throws FederatedUserException
* @throws InvalidIdException
* @throws RequestBuilderException
* @throws RemoteNotFoundException
* @throws UnknownRemoteException
*/
public function manage(FederatedEvent $event): void {
$member = $event->getMember();
if (!$this->memberService->insertOrUpdate($member)) {
return;
}
if ($member->getStatus() === Member::STATUS_REQUEST) {
$this->eventService->memberRequesting($event);
} else {
$this->membershipService->onUpdate($member->getSingleId());
$this->eventService->memberJoining($event);
}
$this->membershipService->updatePopulation($event->getCircle());
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$member = $event->getMember();
if ($member->getStatus() === Member::STATUS_REQUEST) {
$this->eventService->memberRequested($event, $results);
} else {
$this->eventService->memberJoined($event, $results);
}
}
/**
* @param Circle $circle
* @param Member $member
*
* @throws FederatedItemBadRequestException
* @throws RequestBuilderException
*/
private function manageMemberStatus(Circle $circle, Member $member) {
try {
$knownMember = $this->memberRequest->searchMember($member);
if ($knownMember->getLevel() === Member::LEVEL_NONE) {
switch ($knownMember->getStatus()) {
case Member::STATUS_BLOCKED:
throw new Exception('Blocked');
case Member::STATUS_REQUEST:
throw new MemberAlreadyExistsException(StatusCode::$CIRCLE_JOIN[123], 123);
case Member::STATUS_INVITED:
$member->setId($knownMember->getId());
$member->setLevel(Member::LEVEL_MEMBER);
$member->setStatus(Member::STATUS_MEMBER);
return;
}
}
throw new MemberAlreadyExistsException(StatusCode::$CIRCLE_JOIN[122], 122);
} catch (MemberNotFoundException $e) {
if (!$circle->isConfig(Circle::CFG_OPEN)) {
throw new FederatedItemBadRequestException(StatusCode::$CIRCLE_JOIN[124], 124);
}
$member->setId($this->token(ManagedModel::ID_LENGTH));
if ($circle->isConfig(Circle::CFG_REQUEST)) {
$member->setStatus(Member::STATUS_REQUEST);
} else {
$member->setLevel(Member::LEVEL_MEMBER);
$member->setStatus(Member::STATUS_MEMBER);
}
}
}
}
@@ -0,0 +1,258 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Tools\Traits\TNCLogger;
use OCA\Circles\AppInfo\Application;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemInitiatorMembershipNotRequired;
use OCA\Circles\IFederatedItemMemberOptional;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\FederatedUser;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\Probes\CircleProbe;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\MembershipService;
use OCA\Circles\StatusCode;
/**
* Class CircleLeave
*
* @package OCA\Circles\FederatedItems
*/
class CircleLeave implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemAsyncProcess,
IFederatedItemInitiatorMembershipNotRequired,
IFederatedItemMemberOptional {
use TDeserialize;
use TNCLogger;
/** @var MemberRequest */
private $memberRequest;
/** @var CircleRequest */
private $circleRequest;
/** @var MembershipService */
private $membershipService;
/** @var EventService */
private $eventService;
/** @var ConfigService */
private $configService;
/**
* CircleLeave constructor.
*
* @param MemberRequest $memberRequest
* @param CircleRequest $circleRequest
* @param MembershipService $membershipService
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
MemberRequest $memberRequest,
CircleRequest $circleRequest,
MembershipService $membershipService,
EventService $eventService,
ConfigService $configService
) {
$this->memberRequest = $memberRequest;
$this->circleRequest = $circleRequest;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
$this->configService = $configService;
$this->setup('app', Application::APP_ID);
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemException
* @throws RequestBuilderException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$member = $circle->getInitiator();
if (!$event->getParams()->gBool('force')) {
$memberHelper = new MemberHelper($member);
$memberHelper->cannotBeOwner();
} elseif ($this->configService->isLocalInstance($event->getOrigin())) {
if ($member->getLevel() === Member::LEVEL_OWNER) {
try {
$newOwner = $this->selectNewOwner($circle);
$event->getData()->s('newOwnerId', $newOwner->getId());
} catch (MemberNotFoundException $e) {
$event->getData()->sBool('destroyCircle', true);
}
}
}
if ($member->getId() === '') {
try {
// make it works for not-yet-members
$probe = new CircleProbe();
$probe->includeNonVisibleCircles();
$member = $this->memberRequest->getMember(
$circle->getSingleId(),
$member->getSingleId(),
$probe
);
} catch (MemberNotFoundException $e) {
throw new MemberNotFoundException(StatusCode::$CIRCLE_LEAVE[120], 120);
}
}
if ($member->getUserType() !== Member::TYPE_USER) {
throw new MemberNotFoundException(StatusCode::$CIRCLE_LEAVE[121], 121);
}
$event->setMember($member);
$this->memberRequest->delete($member);
$initiator = new FederatedUser();
$initiator->importFromIFederatedUser($member);
try {
$outcome = $this->circleRequest->getCircle($circle->getSingleId(), $initiator);
$event->setOutcome($this->serialize($outcome));
} catch (CircleNotFoundException $e) {
// if member have no visibility on the circle after leaving it, we don't fill outcome
}
}
/**
* @param FederatedEvent $event
*
* @throws RequestBuilderException
* @throws MemberNotFoundException
*/
public function manage(FederatedEvent $event): void {
$member = $event->getMember();
$newOwnerId = $event->getData()->g('newOwnerId');
if ($newOwnerId !== '') {
$newOwner = $this->memberRequest->getMemberById($newOwnerId);
$newOwner->setLevel(Member::LEVEL_OWNER);
$this->memberRequest->updateLevel($newOwner);
$this->membershipService->onUpdate($newOwner->getSingleId());
}
$this->memberRequest->delete($member);
$destroyingCircle = $event->getData()->gBool('destroyCircle');
if ($destroyingCircle) {
$circle = $event->getCircle();
$this->circleRequest->delete($circle);
}
$this->membershipService->onUpdate($member->getSingleId());
$this->eventService->memberLeaving($event);
if ($destroyingCircle) {
$this->membershipService->onUpdate($circle->getSingleId());
$this->eventService->circleDestroying($event);
}
$this->membershipService->updatePopulation($event->getCircle());
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->memberLeft($event, $results);
if ($event->getData()->gBool('destroyCircle')) {
$this->eventService->circleDestroyed($event, $results);
}
}
/**
* @param Circle $circle
*
* @return Member
* @throws RequestBuilderException
* @throws MemberNotFoundException
*/
private function selectNewOwner(Circle $circle): Member {
$members = $this->memberRequest->getMembers($circle->getSingleId());
$newOwner = null;
foreach ($members as $member) {
if ($member->getLevel() === Member::LEVEL_OWNER) {
continue;
}
if (is_null($newOwner)) {
$newOwner = $member;
continue;
}
if ($member->getLevel() > $newOwner->getLevel()) {
$newOwner = $member;
} elseif ($member->getLevel() === $newOwner->getLevel()
&& ($member->getJoined() < $newOwner->getJoined()
|| ($this->configService->isLocalInstance($member->getInstance())
&& !$this->configService->isLocalInstance($newOwner->getInstance()))
)) {
$newOwner = $member;
}
}
if (is_null($newOwner)) {
throw new MemberNotFoundException();
}
return $newOwner;
}
}
@@ -0,0 +1,151 @@
<?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 2022
* @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\FederatedItems;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\ShareTokenService;
use OCA\Circles\Tools\Traits\TDeserialize;
class CircleSetting implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemAsyncProcess {
use TDeserialize;
private CircleRequest $circleRequest;
private ShareTokenService $shareTokenService;
private ConfigService $configService;
public function __construct(
CircleRequest $circleRequest,
ShareTokenService $shareTokenService,
ConfigService $configService
) {
$this->circleRequest = $circleRequest;
$this->shareTokenService = $shareTokenService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$initiatorHelper = new MemberHelper($circle->getInitiator());
$initiatorHelper->mustBeAdmin();
$params = $event->getParams();
$setting = $params->g('setting');
$value = $params->gBool('unset') ? null : $params->g('value');
$settings = $circle->getSettings();
if (!is_null($value)) {
$settings[$setting] = $value;
} elseif (array_key_exists($setting, $settings)) {
unset($settings[$setting]);
}
// in case changed settings is about a static password change,
// refresh password on all previous shares
if ($setting === 'password_single' && $value !== null) {
$event->getData()->sBool('refresh_share_password', true);
}
// in case changed settings is about removing the enforce_password flag
// remove password on previous shares (global configuration will be checked in manage())
if ($setting === 'enforce_password') {
$event->getData()->sBool('remove_share_password', true);
}
$event->getData()->sArray('settings', $settings);
$new = clone $circle;
$new->setSettings($settings);
$event->setOutcome($this->serialize($new));
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
$circle = clone $event->getCircle();
$settings = $event->getData()->gArray('settings');
$circle->setSettings($settings);
// TODO list imported from FederatedItem/CircleConfig.php - need to check first there.
// TODO: Check locally that circle is not un-federated during the process
// TODO: if the circle is managed remotely, remove the circle locally
// TODO: if the circle is managed locally, remove non-local users
// TODO: Check locally that circle is not federated during the process
// TODO: sync if it is to broadcast to Trusted RemoteInstance
$this->circleRequest->updateSettings($circle);
// refresh share password (in case of static password changes)
// only is password are enforced for this Circle
if ($event->getData()->gBool('refresh_share_password')
&& $this->configService->enforcePasswordOnSharedFile($circle)) {
$this->shareTokenService->updateSharePassword(
$circle->getSingleId(),
$settings['password_single'] ?? ''
);
}
// remove share password on request
// only if password are not enforced for this Circle
if ($event->getData()->gBool('remove_share_password')
&& !$this->configService->enforcePasswordOnSharedFile($circle)) {
$this->shareTokenService->removeSharePassword($circle->getSingleId());
}
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,85 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\IFederatedItem;
use OCA\Circles\Model\Federated\FederatedEvent;
/**
* Class CircleSettings
*
* @package OCA\Circles\FederatedItems
*/
class CircleSettings implements IFederatedItem {
use TDeserialize;
/** @var CircleRequest */
private $circleRequest;
/**
* CircleSettings constructor.
*
* @param CircleRequest $circleRequest
*/
public function __construct(CircleRequest $circleRequest) {
$this->circleRequest = $circleRequest;
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$new = clone $circle;
$event->setOutcome($this->serialize($new));
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,134 @@
<?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\FederatedItems\Files;
use OCA\Circles\Tools\Exceptions\InvalidItemException;
use OCA\Circles\Tools\Exceptions\UnknownTypeException;
use OCA\Circles\Tools\Traits\TNCLogger;
use OCA\Circles\Tools\Traits\TStringTools;
use OCA\Circles\Db\MountRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberEmpty;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Mount;
use OCA\Circles\Model\ShareWrapper;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
/**
* Class FileShare
*
* @package OCA\Circles\FederatedItems\Files
*/
class FileShare implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemAsyncProcess,
IFederatedItemMemberEmpty {
use TStringTools;
use TNCLogger;
/** @var MountRequest */
private $mountRequest;
/** @var EventService */
private $eventService;
/** @var ConfigService */
private $configService;
/**
* FileShare constructor.
*
* @param MountRequest $mountRequest
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
MountRequest $mountRequest,
EventService $eventService,
ConfigService $configService
) {
$this->mountRequest = $mountRequest;
$this->eventService = $eventService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
// TODO: check (origin of file ?) and improve
// TODO: Use a share lock
$this->eventService->fileSharePreparing($event);
}
/**
* @param FederatedEvent $event
*
* @throws CircleNotFoundException
* @throws InvalidItemException
* @throws UnknownTypeException
*/
public function manage(FederatedEvent $event): void {
$mount = null;
if (!$this->configService->isLocalInstance($event->getOrigin())) {
/** @var ShareWrapper $wrappedShare */
$wrappedShare = $event->getParams()->gObj('wrappedShare', ShareWrapper::class);
$mount = new Mount();
$mount->fromShare($wrappedShare);
$mount->setMountId($this->token(15));
$this->mountRequest->save($mount);
}
$this->eventService->fileShareCreating($event, $mount);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->fileShareCreated($event, $results);
}
}
@@ -0,0 +1,126 @@
<?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\FederatedItems\Files;
use OCA\Circles\Tools\Exceptions\InvalidItemException;
use OCA\Circles\Tools\Exceptions\ItemNotFoundException;
use OCA\Circles\Tools\Exceptions\UnknownTypeException;
use OCA\Circles\Tools\Traits\TNCLogger;
use OCA\Circles\Tools\Traits\TStringTools;
use OCA\Circles\Db\MountRequest;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberEmpty;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\ShareWrapper;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
/**
* Class FileUnshare
*
* @package OCA\Circles\FederatedItems
*/
class FileUnshare implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemAsyncProcess,
IFederatedItemMemberEmpty {
use TStringTools;
use TNCLogger;
/** @var MountRequest */
private $mountRequest;
/** @var EventService */
private $eventService;
/** @var ConfigService */
private $configService;
/**
* FileUnshare constructor.
*
* @param MountRequest $mountRequest
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
MountRequest $mountRequest,
EventService $eventService,
ConfigService $configService
) {
$this->mountRequest = $mountRequest;
$this->eventService = $eventService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
// TODO: check and improve
// TODO: Could we use a share lock ?
}
/**
* @param FederatedEvent $event
*
* @throws InvalidItemException
* @throws UnknownTypeException
* @throws ItemNotFoundException
*/
public function manage(FederatedEvent $event): void {
if ($this->configService->isLocalInstance($event->getOrigin())) {
return;
}
/** @var ShareWrapper $wrappedShare */
$wrappedShare = $event->getParams()->gObj('wrappedShare', ShareWrapper::class);
$this->mountRequest->delete($wrappedShare->getToken());
$this->eventService->federatedShareDeleted($wrappedShare);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,130 @@
<?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 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\FederatedItems;
use OCA\Circles\Tools\Traits\TStringTools;
use OCA\Circles\Db\ShareLockRequest;
use OCA\Circles\Exceptions\FederatedShareNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemDataRequestOnly;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Federated\FederatedShare;
/**
* Class ItemLock
*
* @package OCA\Circles\FederatedItems
*/
class ItemLock implements
IFederatedItem,
IFederatedItemDataRequestOnly {
use TStringTools;
public const STATUS_LOCKED = 'locked';
public const STATUS_ALREADY_LOCKED = 'already_locked';
public const STATUS_INSTANCE_LOCKED = 'instance_locked';
/** @var ShareLockRequest */
private $shareLockRequest;
/**
* ItemLock constructor.
*
* @param ShareLockRequest $shareLockRequest
*/
public function __construct(ShareLockRequest $shareLockRequest) {
$this->shareLockRequest = $shareLockRequest;
}
/**
* create lock in db if the lock does not exist for this circle.
* will fail if the lock already exist for anothr instance, even for another circle
*
* @param FederatedEvent $event
*
* @throws InvalidIdException
* @throws FederatedShareNotFoundException
*/
public function verify(FederatedEvent $event): void {
$itemId = $event->getParams()->g('itemId');
$this->shareLockRequest->confirmValidId($itemId);
$status = '';
try {
$known = $this->shareLockRequest->getShare($itemId);
if ($known->getInstance() === $event->getSender()) {
$status = self::STATUS_ALREADY_LOCKED;
$known = $this->shareLockRequest->getShare($itemId, $event->getCircle()->getSingleId());
} else {
$status = self::STATUS_INSTANCE_LOCKED;
}
} catch (FederatedShareNotFoundException $e) {
$share = new FederatedShare();
$share->setItemId($itemId);
$share->setCircleId($event->getCircle()->getSingleId());
$share->setInstance($event->getSender());
$this->shareLockRequest->save($share);
$known = $this->shareLockRequest->getShare($itemId);
if ($status === '') {
$status = self::STATUS_LOCKED;
}
}
$known->setLockStatus($status);
$event->setOutcome(['federatedShare' => $known]);
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
// $this->circleEventService->onSharedItemsSyncRequested($event);
//
// $event->setResult(new SimpleDataStore(['shares' => 'ok']));
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,82 @@
<?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 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\FederatedItems;
use OCA\Circles\Tools\Model\SimpleDataStore;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemLoopbackTest;
use OCA\Circles\Model\Federated\FederatedEvent;
/**
* Class LoopbackTest
*
* @package OCA\Circles\FederatedItems
*/
class LoopbackTest implements
IFederatedItem,
IFederatedItemAsyncProcess,
IFederatedItemLoopbackTest {
public const VERIFY = 17;
public const MANAGE = 42;
/**
* LoopbackTest constructor.
*/
public function __construct() {
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
$event->setData(new SimpleDataStore(['verify' => self::VERIFY]));
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
$event->setResult(new SimpleDataStore(['manage' => self::MANAGE]));
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,127 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TNCLogger;
use OCA\Circles\Tools\Traits\TStringTools;
use Exception;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberEmpty;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Model\Member;
/**
* Class MemberAdd
*
* @package OCA\Circles\GlobalScale
*/
class MassiveMemberAdd extends SingleMemberAdd implements
IFederatedItem,
IFederatedItemAsyncProcess,
IFederatedItemHighSeverity,
IFederatedItemMemberEmpty {
use TStringTools;
use TNCLogger;
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$initiator = $circle->getInitiator();
$initiatorHelper = new MemberHelper($initiator);
if (!$circle->isConfig(Circle::CFG_FRIEND)) {
$initiatorHelper->mustBeModerator();
}
$members = $event->getMembers();
$filtered = [];
foreach ($members as $member) {
try {
$filtered[] = $this->generateMember($event, $circle, $member);
} catch (Exception $e) {
$this->e($e, ['event' => $event->getWrapperToken()]);
}
}
$event->setMembers($filtered);
$event->setOutcome($this->serializeArray($filtered));
foreach ($event->getMembers() as $member) {
$event->setMember($member);
$this->eventService->memberPreparing($event);
}
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
foreach ($event->getMembers() as $member) {
try {
if (!$this->memberService->insertOrUpdate($member)) {
continue;
}
$event->setMember($member);
if ($member->getStatus() === Member::STATUS_INVITED) {
$this->eventService->memberInviting($event);
} else {
$this->eventService->memberAdding($event);
}
} catch (Exception $e) {
}
}
$this->membershipService->updatePopulation($event->getCircle());
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
foreach ($event->getMembers() as $member) {
$event->setMember($member);
$this->eventService->memberAdded($event, $results);
}
}
}
@@ -0,0 +1,145 @@
<?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 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\FederatedItems;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemInitiatorMembershipNotRequired;
use OCA\Circles\IFederatedItemMemberEmpty;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\MembershipService;
use OCA\Circles\StatusCode;
use OCA\Circles\Tools\Traits\TDeserialize;
/**
* Class MemberDisplayName
*
* @package OCA\Circles\FederatedItems
*/
class MemberDisplayName implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemInitiatorMembershipNotRequired,
IFederatedItemMemberEmpty {
use TDeserialize;
/** @var MemberRequest */
private $memberRequest;
/** @var MembershipService */
private $membershipService;
/** @var EventService */
private $eventService;
/** @var ConfigService */
private $configService;
/**
* MemberDisplayName constructor.
*
* @param MemberRequest $memberRequest
* @param MembershipService $membershipService
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
MemberRequest $memberRequest,
MembershipService $membershipService,
EventService $eventService,
ConfigService $configService
) {
$this->memberRequest = $memberRequest;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemException
* @throws FederatedItemBadRequestException
* @throws MemberLevelException
*/
public function verify(FederatedEvent $event): void {
$member = $event->getCircle()
->getInitiator();
$displayName = $event->getParams()->g('displayName');
if ($displayName === '') {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_DISPLAY_NAME[120], 120);
}
$event->getData()->s('displayName', $displayName);
$outcomeMember = clone $member;
$outcomeMember->setDisplayName($displayName);
$event->setOutcome($this->serialize($outcomeMember));
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
$circle = $event->getCircle();
$member = $circle->getInitiator();
$displayName = $event->getData()->g('displayName');
$member->setDisplayName($displayName);
$this->memberRequest->updateDisplayName($member->getSingleId(), $displayName, $circle->getSingleId());
$event->setMember($member);
$this->eventService->memberNameEditing($event);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->memberNameEdited($event, $results);
}
}
@@ -0,0 +1,216 @@
<?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 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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberRequired;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\MembershipService;
/**
* Class MemberLevel
*
* @package OCA\Circles\FederatedItems
*/
class MemberLevel implements
IFederatedItem,
IFederatedItemHighSeverity,
IFederatedItemMemberRequired {
use TDeserialize;
/** @var MemberRequest */
private $memberRequest;
/** @var MembershipService */
private $membershipService;
/** @var EventService */
private $eventService;
/** @var ConfigService */
private $configService;
/**
* MemberAdd constructor.
*
* @param MemberRequest $memberRequest
* @param MembershipService $membershipService
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
MemberRequest $memberRequest,
MembershipService $membershipService,
EventService $eventService,
ConfigService $configService
) {
$this->memberRequest = $memberRequest;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemException
* @throws FederatedItemBadRequestException
* @throws MemberLevelException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$member = $event->getMember();
$initiator = $circle->getInitiator();
$level = $event->getParams()->gInt('level');
if ($circle->isConfig(Circle::CFG_SINGLE) || $circle->isConfig(Circle::CFG_PERSONAL)) {
throw new FederatedItemBadRequestException('This level cannot be edited');
}
if ($level === 0) {
// TODO check all level
throw new FederatedItemBadRequestException('invalid level');
}
if ($member->getLevel() === $level) {
throw new FederatedItemBadRequestException('This member already have the selected level');
}
$initiatorHelper = new MemberHelper($initiator);
$initiatorHelper->mustBeModerator();
if ($level === Member::LEVEL_OWNER) {
$this->verifySwitchOwner($member, $initiator);
} else {
$this->verifyMemberLevel($member, $initiator, $level);
}
$event->getData()->sInt('level', $level);
$outcomeMember = clone $member;
$outcomeMember->setLevel($level);
$event->setOutcome($this->serialize($outcomeMember));
}
/**
* @param FederatedEvent $event
*
* @throws RequestBuilderException
*/
public function manage(FederatedEvent $event): void {
$member = clone $event->getMember();
$member->setLevel($event->getData()->gInt('level'));
$this->memberRequest->updateLevel($member);
if ($member->getLevel() === Member::LEVEL_OWNER) {
$oldOwner = clone $event->getCircle()->getOwner();
$oldOwner->setLevel(Member::LEVEL_ADMIN);
$this->memberRequest->updateLevel($oldOwner);
$this->membershipService->onUpdate($oldOwner->getSingleId());
}
$this->membershipService->onUpdate($member->getSingleId());
$this->eventService->memberLevelEditing($event);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->memberLevelEdited($event, $results);
}
/**
* @param Member $member
* @param Member $initiator
* @param int $level
*
* @throws MemberLevelException
*/
private function verifyMemberLevel(Member $member, Member $initiator, int $level) {
$initiatorHelper = new MemberHelper($initiator);
$memberHelper = new MemberHelper($member);
$memberHelper->mustBeMember();
$memberHelper->cannotBeOwner();
$initiatorHelper->mustBeModerator();
switch ($this->configService->getAppValueInt(ConfigService::HARD_MODERATION)) {
case 0:
$initiatorHelper->mustHaveLevelAboveOrEqual($level);
$initiatorHelper->mustBeHigherOrSameLevelThan($member);
break;
case 1:
$initiatorHelper->mustHaveLevelAboveOrEqual($level);
$initiatorHelper->mustBeHigherLevelThan($member);
break;
case 2:
$initiatorHelper->mustHaveLevelAbove($level);
$initiatorHelper->mustBeHigherLevelThan($member);
break;
}
}
/**
* @param Member $member
* @param Member $initiator
*/
private function verifySwitchOwner(Member $member, Member $initiator) {
// TODO: check on NO_OWNER circle
$initiatorHelper = new MemberHelper($initiator);
$memberHelper = new MemberHelper($member);
$initiatorHelper->mustBeOwner();
$memberHelper->mustBeMember();
$memberHelper->cannotBeOwner();
}
}
@@ -0,0 +1,129 @@
<?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 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\FederatedItems;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberRequired;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\MembershipService;
/**
* Class MemberLevel
*
* @package OCA\Circles\FederatedItems
*/
class MemberRemove implements
IFederatedItem,
IFederatedItemAsyncProcess,
IFederatedItemHighSeverity,
IFederatedItemMemberRequired {
/** @var MemberRequest */
private $memberRequest;
/** @var MembershipService */
private $membershipService;
/** @var EventService */
private $eventService;
/**
* MemberAdd constructor.
*
* @param MemberRequest $memberRequest
* @param MembershipService $membershipService
* @param EventService $eventService
*/
public function __construct(
MemberRequest $memberRequest,
MembershipService $membershipService,
EventService $eventService
) {
$this->memberRequest = $memberRequest;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
$member = $event->getMember();
$initiator = $circle->getInitiator();
$initiatorHelper = new MemberHelper($initiator);
$initiatorHelper->mustBeModerator();
$initiatorHelper->mustBeHigherLevelThan($member);
$memberHelper = new MemberHelper($member);
$memberHelper->cannotBeOwner();
$event->setOutcome([]);
}
/**
* @param FederatedEvent $event
*
* @throws RequestBuilderException
*/
public function manage(FederatedEvent $event): void {
$member = $event->getMember();
$this->memberRequest->delete($member);
$this->membershipService->onUpdate($member->getSingleId());
// TODO: Remove invited members from this user that have not accepted their invitation
$this->eventService->memberRemoving($event);
$this->membershipService->updatePopulation($event->getCircle());
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$this->eventService->memberRemoved($event, $results);
}
}
@@ -0,0 +1,83 @@
<?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 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\FederatedItems;
use OCA\Circles\Tools\Model\SimpleDataStore;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemLimitedToInstanceWithMembership;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Service\CircleEventService;
/**
* Class SharesSync
*
* @package OCA\Circles\FederatedItems
*/
class SharedItemsSync implements
IFederatedItem,
IFederatedItemLimitedToInstanceWithMembership {
// TODO: testing that IFederatedItemLimitedToInstanceWithMembership is working (since multi-instance)
// TODO: implements IFederatedItemInstanceMember to the check procedure
/** @var CircleEventService */
private $circleEventService;
public function __construct(CircleEventService $circleEventService) {
$this->circleEventService = $circleEventService;
}
/**
* @param FederatedEvent $event
*/
public function verify(FederatedEvent $event): void {
}
/**
* @param FederatedEvent $event
*/
public function manage(FederatedEvent $event): void {
$this->circleEventService->onSharedItemsSyncRequested($event);
$event->setResult(new SimpleDataStore(['shares' => 'ok']));
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
}
}
@@ -0,0 +1,449 @@
<?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\FederatedItems;
use OCA\Circles\Tools\Traits\TDeserialize;
use OCA\Circles\Tools\Traits\TNCLogger;
use OCA\Circles\Tools\Traits\TStringTools;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedItemNotFoundException;
use OCA\Circles\Exceptions\FederatedItemRemoteException;
use OCA\Circles\Exceptions\FederatedItemServerException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\MembersLimitException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteInstanceException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Exceptions\UserTypeNotFoundException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemAsyncProcess;
use OCA\Circles\IFederatedItemHighSeverity;
use OCA\Circles\IFederatedItemMemberCheckNotRequired;
use OCA\Circles\IFederatedItemMemberRequired;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Model\ManagedModel;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\EventService;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use OCA\Circles\Service\MembershipService;
use OCA\Circles\Service\RemoteStreamService;
use OCA\Circles\StatusCode;
use OCP\IUserManager;
/**
* Class SingleMemberAdd
*
* @package OCA\Circles\FederatedItems
*/
class SingleMemberAdd implements
IFederatedItem,
IFederatedItemAsyncProcess,
IFederatedItemHighSeverity,
IFederatedItemMemberRequired,
IFederatedItemMemberCheckNotRequired {
use TDeserialize;
use TStringTools;
use TNCLogger;
/** @var IUserManager */
protected $userManager;
/** @var MemberRequest */
protected $memberRequest;
/** @var FederatedUserService */
protected $federatedUserService;
/** @var RemoteStreamService */
protected $remoteStreamService;
/** @var CircleService */
protected $circleService;
/** @var MemberService */
protected $memberService;
/** @var MembershipService */
protected $membershipService;
/** @var EventService */
protected $eventService;
/** @var ConfigService */
protected $configService;
/**
* SingleMemberAdd constructor.
*
* @param IUserManager $userManager
* @param MemberRequest $memberRequest
* @param FederatedUserService $federatedUserService
* @param RemoteStreamService $remoteStreamService
* @param CircleService $circleService
* @param MemberService $memberService
* @param MembershipService $membershipService
* @param EventService $eventService
* @param ConfigService $configService
*/
public function __construct(
IUserManager $userManager,
MemberRequest $memberRequest,
FederatedUserService $federatedUserService,
RemoteStreamService $remoteStreamService,
CircleService $circleService,
MemberService $memberService,
MembershipService $membershipService,
EventService $eventService,
ConfigService $configService
) {
$this->userManager = $userManager;
$this->memberRequest = $memberRequest;
$this->federatedUserService = $federatedUserService;
$this->remoteStreamService = $remoteStreamService;
$this->circleService = $circleService;
$this->memberService = $memberService;
$this->membershipService = $membershipService;
$this->eventService = $eventService;
$this->configService = $configService;
}
/**
* @param FederatedEvent $event
*
* @throws FederatedItemBadRequestException
* @throws FederatedItemNotFoundException
* @throws FederatedItemServerException
* @throws FederatedItemRemoteException
* @throws FederatedItemException
* @throws RequestBuilderException
*/
public function verify(FederatedEvent $event): void {
$member = $event->getMember();
$circle = $event->getCircle();
$initiator = $circle->getInitiator();
$initiatorHelper = new MemberHelper($initiator);
if (!$circle->isConfig(Circle::CFG_FRIEND)) {
$initiatorHelper->mustBeModerator();
}
$member = $this->generateMember($event, $circle, $member);
$event->setMembers([$member]);
$event->setOutcome($this->serialize($member));
$this->eventService->memberPreparing($event);
}
/**
* @param FederatedEvent $event
*
* @throws InvalidIdException
* @throws RemoteNotFoundException
* @throws RequestBuilderException
* @throws UnknownRemoteException
*/
public function manage(FederatedEvent $event): void {
$member = $event->getMember();
if (!$this->memberService->insertOrUpdate($member)) {
return;
}
if ($member->getStatus() === Member::STATUS_INVITED) {
$this->eventService->memberInviting($event);
} else {
$this->eventService->memberAdding($event);
}
$this->membershipService->updatePopulation($event->getCircle());
// //
// // TODO: verifiez comment se passe le cached name sur un member_add
// //
// $cachedName = $member->getCachedName();
// $password = $event->getData()
// ->g('password');
//
// $shares = $this->generateUnknownSharesLinks($circle, $member, $password);
// $result = [
// 'unknownShares' => $shares,
// 'cachedName' => $cachedName
// ];
//
// if ($member->getType() === DeprecatedMember::TYPE_CONTACT
// && $this->configService->isLocalInstance($member->getInstance())) {
// $result['contact'] = $this->miscService->getInfosFromContact($member);
// }
//
// $event->setResult(new SimpleDataStore($result));
// $this->eventsService->onMemberNew($circle, $member);
}
/**
* @param FederatedEvent $event
* @param array $results
*/
public function result(FederatedEvent $event, array $results): void {
$member = $event->getMember();
if ($member->getStatus() === Member::STATUS_INVITED) {
$this->eventService->memberInvited($event, $results);
} else {
$this->eventService->memberAdded($event, $results);
}
// $password = $cachedName = '';
// $circle = $member = null;
// $links = [];
// $recipients = [];
// foreach ($events as $event) {
// $data = $event->getData();
// if ($data->gBool('passwordByMail') !== false) {
// $password = $data->g('password');
// }
// $circle = $event->getDeprecatedCircle();
// $member = $event->getMember();
// $result = $event->getResult();
// if ($result->g('cachedName') !== '') {
// $cachedName = $result->g('cachedName');
// }
//
// $links = array_merge($links, $result->gArray('unknownShares'));
// $contact = $result->gArray('contact');
// if (!empty($contact)) {
// $recipients = $contact['emails'];
// }
// }
//
// if (empty($links) || $circle === null || $member === null) {
// return;
// }
//
// if ($cachedName !== '') {
// $member->setCachedName($cachedName);
// $this->membersService->updateMember($member);
// }
//
// if ($member->getType() === DeprecatedMember::TYPE_MAIL
// || $member->getType() === DeprecatedMember::TYPE_CONTACT) {
// if ($member->getType() === DeprecatedMember::TYPE_MAIL) {
// $recipients = [$member->getUserId()];
// }
//
// foreach ($recipients as $recipient) {
// $this->memberIsMailbox($circle, $recipient, $links, $password);
// }
// }
}
/**
* @param FederatedEvent $event
* @param Circle $circle
* @param Member $member
*
* @return Member
* @throws CircleNotFoundException
* @throws FederatedItemBadRequestException
* @throws FederatedItemException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidIdException
* @throws MembersLimitException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws SingleCircleNotFoundException
* @throws UnknownRemoteException
* @throws UserTypeNotFoundException
* @throws RequestBuilderException
*/
protected function generateMember(FederatedEvent $event, Circle $circle, Member $member): Member {
try {
if ($member->getSingleId() !== '') {
$userId = $member->getSingleId() . '@' . $member->getInstance();
$federatedUser = $this->federatedUserService->getFederatedUser($userId, Member::TYPE_SINGLE);
} else {
$userId = $member->getUserId() . '@' . $member->getInstance();
$federatedUser = $this->federatedUserService->getFederatedUser(
$userId,
$member->getUserType()
);
}
} catch (MemberNotFoundException $e) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[120], 120);
}
$allowedTypes = $this->configService->getAppValueInt(ConfigService::ALLOWED_TYPES);
if ($federatedUser->getUserType() < Member::TYPE_APP
&& ($allowedTypes & $federatedUser->getUserType()) === 0) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[132], 132);
}
if ($federatedUser->getBasedOn()->isConfig(Circle::CFG_ROOT)) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[125], 125);
}
if ($circle->isConfig(Circle::CFG_LOCAL)
&& $federatedUser->getUserType() === Member::TYPE_CIRCLE
&& !$federatedUser->getBasedOn()->isConfig(Circle::CFG_LOCAL)) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[131], 131);
}
if ($member->getSingleId() === $circle->getSingleId()) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[128], 128);
}
if (!$this->configService->isLocalInstance($member->getInstance())) {
if ($circle->isConfig(Circle::CFG_LOCAL)) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[126], 126);
}
if (!$circle->isConfig(Circle::CFG_FEDERATED)) {
$remoteInstance = $this->remoteStreamService->getCachedRemoteInstance($member->getInstance());
if ($remoteInstance->getType() !== RemoteInstance::TYPE_GLOBALSCALE) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[127], 127);
}
}
}
$member->importFromIFederatedUser($federatedUser);
$member->setCircleId($circle->getSingleId());
$member->setCircle($circle);
$this->confirmPatron($event, $member);
$this->manageMemberStatus($circle, $member);
$this->circleService->confirmCircleNotFull($circle);
// The idea is that adding the member during the self::verify() will help during the broadcasting
// of the event to Federated RemoteInstance for their first member.
$this->memberRequest->insertOrUpdate($member);
return $member;
}
/**
* @param Circle $circle
* @param Member $member
*
* @throws FederatedItemBadRequestException
* @throws RequestBuilderException
*/
private function manageMemberStatus(Circle $circle, Member $member) {
try {
$knownMember = $this->memberRequest->searchMember($member);
$member->setId($knownMember->getId());
if ($knownMember->getLevel() === Member::LEVEL_NONE) {
switch ($knownMember->getStatus()) {
case Member::STATUS_BLOCKED:
if ($circle->isConfig(Circle::CFG_INVITE)) {
$member->setStatus(Member::STATUS_INVITED);
}
return;
case Member::STATUS_REQUEST:
$member->setLevel(Member::LEVEL_MEMBER);
$member->setStatus(Member::STATUS_MEMBER);
return;
case Member::STATUS_INVITED:
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[123], 123);
}
}
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[122], 122);
} catch (MemberNotFoundException $e) {
$member->setId($this->token(ManagedModel::ID_LENGTH));
if ($circle->isConfig(Circle::CFG_INVITE)
&& $member->getUserType() !== Member::TYPE_MAIL
&& $member->getUserType() !== Member::TYPE_CONTACT) {
$member->setStatus(Member::STATUS_INVITED);
} else {
$member->setLevel(Member::LEVEL_MEMBER);
$member->setStatus(Member::STATUS_MEMBER);
}
}
}
/**
* @param FederatedEvent $event
* @param Member $member
*
* @throws FederatedItemBadRequestException
* @throws FederatedUserException
* @throws RemoteNotFoundException
* @throws RequestBuilderException
* @throws UnknownRemoteException
*/
private function confirmPatron(FederatedEvent $event, Member $member): void {
if (!$member->hasInvitedBy()) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[129], 129);
}
$patron = $member->getInvitedBy();
if ($patron->getInstance() !== $event->getSender()) {
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[130], 130);
}
$this->federatedUserService->confirmSingleIdUniqueness($patron);
}
}