From fe742d7e6e3f59b660aedf7473a9133177d860e7 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Tue, 14 Apr 2020 16:55:40 -0100 Subject: [PATCH] onUserDeleted Signed-off-by: Maxence Lange --- lib/Db/CirclesRequest.php | 1 - lib/Db/MembersRequest.php | 14 ++- lib/Events/UserEvents.php | 7 +- lib/GlobalScale/MemberLevel.php | 12 --- lib/GlobalScale/UserDeleted.php | 160 ++++++++++++++++++++++++++++ lib/Model/GlobalScale/GSEvent.php | 1 + lib/Service/CirclesService.php | 50 +-------- lib/Service/GSDownstreamService.php | 6 +- lib/Service/MembersService.php | 18 +++- 9 files changed, 191 insertions(+), 78 deletions(-) create mode 100644 lib/GlobalScale/UserDeleted.php diff --git a/lib/Db/CirclesRequest.php b/lib/Db/CirclesRequest.php index d97b17c90..984d2dc8c 100644 --- a/lib/Db/CirclesRequest.php +++ b/lib/Db/CirclesRequest.php @@ -132,7 +132,6 @@ public function forceGetCircleByName($name) { /** * @param string $userId - * @param string $instanceId * @param int $type * @param string $name * @param int $level diff --git a/lib/Db/MembersRequest.php b/lib/Db/MembersRequest.php index f07fdcc7e..c4fc5cd10 100644 --- a/lib/Db/MembersRequest.php +++ b/lib/Db/MembersRequest.php @@ -598,20 +598,26 @@ public function removeAllFromCircle($uniqueCircleId) { * * remove All membership from a User. Used when removing a User from the Cloud. * - * @param string $userId + * @param Member $member */ - public function removeAllMembershipsFromUser($userId) { - if ($userId === '') { + public function removeAllMembershipsFromUser(Member $member) { + if ($member->getUserId() === '') { return; } + $instance = $member->getInstance(); + if ($instance === $this->configService->getLocalCloudId()) { + $instance = ''; + } + $qb = $this->getMembersDeleteSql(); $expr = $qb->expr(); /** @noinspection PhpMethodParametersCountMismatchInspection */ $qb->where( $expr->andX( - $expr->eq('user_id', $qb->createNamedParameter($userId)), + $expr->eq('user_id', $qb->createNamedParameter($member->getUserId())), + $expr->eq('instance', $qb->createNamedParameter($instance)), $expr->eq('user_type', $qb->createNamedParameter(Member::TYPE_USER)) ) ); diff --git a/lib/Events/UserEvents.php b/lib/Events/UserEvents.php index 8b8986a94..e7e2e28a4 100644 --- a/lib/Events/UserEvents.php +++ b/lib/Events/UserEvents.php @@ -47,8 +47,11 @@ public function __construct( */ public function onUserDeleted(array $params) { $userId = $params['uid']; - $this->circlesService->onUserRemoved($userId); - $this->membersService->onUserRemoved($userId); + try { + $this->membersService->onUserRemoved($userId); + } catch (\Exception $e) { + $this->miscService->log('exception while onUserDeleted ' . $e->getMessage()); + } } diff --git a/lib/GlobalScale/MemberLevel.php b/lib/GlobalScale/MemberLevel.php index d2f69b90a..4b769c3f9 100644 --- a/lib/GlobalScale/MemberLevel.php +++ b/lib/GlobalScale/MemberLevel.php @@ -86,8 +86,6 @@ public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChe $this->verifyMemberLevel($event, $circle, $member, $level); } - $this->miscService->log('$$$$ 3 ' . json_encode($event)); - } @@ -100,16 +98,12 @@ public function manage(GSEvent $event): void { $level = $event->getData() ->gInt('level'); - $this->miscService->log('$$$$ 4 ' . json_encode($event)); - $member = $event->getMember(); $this->cleanMember($member); - $this->miscService->log('$$$$ 5 ' . json_encode($event)); $member->setLevel($level); $this->membersRequest->updateMember($member); - $this->miscService->log('#### ' . json_encode($event)); if ($level === Member::LEVEL_OWNER) { $circle = $event->getCircle(); $isMod = $circle->getOwner(); @@ -117,14 +111,8 @@ public function manage(GSEvent $event): void { $isMod->setInstance($event->getSource()); } - $this->miscService->log('???? ' . $isMod->getInstance()); - $isMod->setLevel(Member::LEVEL_ADMIN); - $this->miscService->log('#### 001 ' . json_encode($event)); - $this->membersRequest->updateMember($isMod); - $this->miscService->log('#### 002 ' . json_encode($event)); - } } diff --git a/lib/GlobalScale/UserDeleted.php b/lib/GlobalScale/UserDeleted.php new file mode 100644 index 000000000..6c68d6f49 --- /dev/null +++ b/lib/GlobalScale/UserDeleted.php @@ -0,0 +1,160 @@ + + * @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 . + * + */ + + +namespace OCA\Circles\GlobalScale; + + +use OCA\Circles\Exceptions\CircleDoesNotExistException; +use OCA\Circles\Exceptions\ConfigNoCircleAvailableException; +use OCA\Circles\Exceptions\GlobalScaleDSyncException; +use OCA\Circles\Exceptions\GlobalScaleEventException; +use OCA\Circles\Exceptions\MemberDoesNotExistException; +use OCA\Circles\Model\Circle; +use OCA\Circles\Model\GlobalScale\GSEvent; +use OCA\Circles\Model\Member; + + +/** + * Class MemberDelete + * + * @package OCA\Circles\GlobalScale + */ +class UserDeleted extends AGlobalScaleEvent { + + + /** + * @param GSEvent $event + * @param bool $localCheck + * @param bool $mustBeChecked + * + * @throws CircleDoesNotExistException + * @throws ConfigNoCircleAvailableException + * @throws GlobalScaleDSyncException + * @throws GlobalScaleEventException + */ + public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChecked = false): void { + parent::verify($event, $localCheck, true); + + $member = $event->getMember(); + $circles = $this->circlesRequest->getCircles($member->getUserId(), 0, '', Member::LEVEL_OWNER); + + $destroyedCircles = []; + $promotedAdmins = []; + foreach ($circles as $circle) { + $members = + $this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MEMBER); + + if ($circle->getType() === Circle::CIRCLES_PERSONAL || sizeof($members) === 1) { + $destroyedCircles[] = $circle->getUniqueId(); + continue; + } + + $promotedAdmins[] = $this->getOlderAdmin($members); + } + + $event->getData() + ->sArray('destroyedCircles', $destroyedCircles) + ->sArray('promotedAdmins', $promotedAdmins); + + $this->miscService->log(json_encode($event->getData())); + } + + + /** + * @param GSEvent[] $events + */ + public function result(array $events): void { + } + + + /** + * @param GSEvent $event + */ + public function manage(GSEvent $event): void { + $member = $event->getMember(); + + $this->membersRequest->removeAllMembershipsFromUser($member); + + $data = $event->getData(); + $this->destroyCircles($data->gArray('destroyedCircles')); + $this->promotedAdmins($data->gArray('promotedAdmins')); + } + + + /** + * @param Member[] $members + * + * @return string + */ + private function getOlderAdmin(array $members) { + foreach ($members as $member) { + if ($member->getLevel() === Member::LEVEL_ADMIN) { + return $member->getMemberId(); + } + } + foreach ($members as $member) { + if ($member->getLevel() === Member::LEVEL_MODERATOR) { + return $member->getMemberId(); + } + } + foreach ($members as $member) { + if ($member->getLevel() === Member::LEVEL_MEMBER) { + return $member->getMemberId(); + } + } + } + + + /** + * @param array $circleIds + */ + private function destroyCircles(array $circleIds) { + foreach ($circleIds as $circleId) { + $this->circlesRequest->destroyCircle($circleId); + $this->membersRequest->removeAllFromCircle($circleId); + } + } + + + /** + * @param array $memberIds + */ + private function promotedAdmins(array $memberIds) { + foreach ($memberIds as $memberId) { + try { + $member = $this->membersRequest->forceGetMemberById($memberId); + $member->setLevel(Member::LEVEL_OWNER); + $this->membersRequest->updateMember($member); + } catch (MemberDoesNotExistException $e) { + } + } + } + +} + diff --git a/lib/Model/GlobalScale/GSEvent.php b/lib/Model/GlobalScale/GSEvent.php index 417483358..9d2426ea4 100644 --- a/lib/Model/GlobalScale/GSEvent.php +++ b/lib/Model/GlobalScale/GSEvent.php @@ -63,6 +63,7 @@ class GSEvent implements JsonSerializable { const MEMBER_LEVEL = 'GlobalScale\MemberLevel'; const MEMBER_UPDATE = 'GlobalScale\MemberUpdate'; const MEMBER_REMOVE = 'GlobalScale\MemberRemove'; + const USER_DELETED = 'GlobalScale\UserDeleted'; const FILE_SHARE = 'GlobalScale\FileShare'; diff --git a/lib/Service/CirclesService.php b/lib/Service/CirclesService.php index 7a4d4c2d3..1a9eeeda9 100644 --- a/lib/Service/CirclesService.php +++ b/lib/Service/CirclesService.php @@ -442,54 +442,6 @@ public function infoCircleByName($circleName) { } - /** - * // TODO - check this on GS setup - * When a user is removed. - * Before deleting a user from the cloud, we assign a new owner to his Circles. - * Remove the Circle if it has no admin. - * - * @param string $userId - */ - public function onUserRemoved($userId) { - $circles = $this->circlesRequest->getCircles($userId, 0, '', Member::LEVEL_OWNER); - - foreach ($circles as $circle) { - - $members = - $this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_ADMIN); - - if (sizeof($members) === 1) { - $this->circlesRequest->destroyCircle($circle->getUniqueId()); - continue; - } - - $this->switchOlderAdminToOwner($circle, $members); - } - } - - - /** - * // TODO - check this on GS setup - * switchOlderAdminToOwner(); - * - * @param Circle $circle - * @param Member[] $members - */ - private function switchOlderAdminToOwner(Circle $circle, $members) { - - foreach ($members as $member) { - if ($member->getLevel() === Member::LEVEL_ADMIN) { - $member->setLevel(Member::LEVEL_OWNER); - $this->membersRequest->updateMember($member); - $this->eventsService->onMemberOwner($circle, $member); - - return; - } - } - - } - - /** * Convert a Type in String to its Bit Value * @@ -587,7 +539,7 @@ public function checkThatCircleIsNotFull(Circle $circle) { $circle->getUniqueId(), Member::LEVEL_MEMBER, true ); - $limit = (int) $circle->getSetting('members_limit'); + $limit = (int)$circle->getSetting('members_limit'); if ($limit === -1) { return; } diff --git a/lib/Service/GSDownstreamService.php b/lib/Service/GSDownstreamService.php index 3b8cf7bcd..09043eb83 100644 --- a/lib/Service/GSDownstreamService.php +++ b/lib/Service/GSDownstreamService.php @@ -118,13 +118,8 @@ public function requestedEvent(GSEvent $event) { $gs = $this->globalScaleService->getGlobalScaleEvent($event); $gs->verify($event, true); - - $this->miscService->log('&&&& 1 ' . json_encode($event)); - $gs->manage($event); - $this->miscService->log('&&&& 2 ' . json_encode($event)); - $this->globalScaleService->asyncBroadcast($event); } @@ -157,6 +152,7 @@ public function onNewEvent(GSEvent $event) { $gs = $this->globalScaleService->getGlobalScaleEvent($event); $gs->manage($event); } catch (Exception $e) { + $this->miscService->log('issue onNewEvent - ' . $e->getMessage()); } } diff --git a/lib/Service/MembersService.php b/lib/Service/MembersService.php index 60b85c093..a9d790188 100644 --- a/lib/Service/MembersService.php +++ b/lib/Service/MembersService.php @@ -422,6 +422,7 @@ private function addGroupMembers(Circle $circle, $groupId) { /** * // TODO - check this on GS setup + * * @param Circle $circle * @param string $mails * @@ -588,14 +589,21 @@ public function removeMember( /** - * // TODO - check this on GS setup * When a user is removed, remove him from all Circles * - * @param $userId + * @param string $userId + * + * @throws Exception */ - public function onUserRemoved($userId) { - // TODO: broadcast the event to all instances - $this->membersRequest->removeAllMembershipsFromUser($userId); + public function onUserRemoved(string $userId) { + $event = new GSEvent(GSEvent::USER_DELETED, true, true); + + $member = new Member($userId); + $event->setMember($member); + $event->getData() + ->s('userId', $userId); + + $this->gsUpstreamService->newEvent($event); }