From beb37be3fb631762cd109297fc13ffea629af15b Mon Sep 17 00:00:00 2001 From: samin-z Date: Tue, 16 Jun 2026 17:18:02 +0200 Subject: [PATCH 1/3] apply remove share for users/teams/groups Signed-off-by: samin-z --- lib/AppInfo/Application.php | 7 +++ lib/Db/ShareMapper.php | 12 ++++++ lib/Listener/ReceiverCleanupListener.php | 54 ++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 lib/Listener/ReceiverCleanupListener.php diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 4c00c491df..d9cf8e2d93 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -9,6 +9,7 @@ use Exception; use OCA\Analytics\Datasource\DatasourceEvent; +use OCA\Circles\Events\CircleDestroyedEvent; use OCA\Tables\Capabilities; use OCA\Tables\Event\RowDeletedEvent; use OCA\Tables\Event\TableDeletedEvent; @@ -18,6 +19,7 @@ use OCA\Tables\Listener\AnalyticsDatasourceListener; use OCA\Tables\Listener\BeforeTemplateRenderedListener; use OCA\Tables\Listener\LoadAdditionalListener; +use OCA\Tables\Listener\ReceiverCleanupListener; use OCA\Tables\Listener\TablesReferenceListener; use OCA\Tables\Listener\UserDeletedListener; use OCA\Tables\Listener\WhenRowDeletedAuditLogListener; @@ -40,7 +42,9 @@ use OCP\Collaboration\Reference\RenderReferenceEvent; use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent; use OCP\DB\Events\AddMissingIndicesEvent; +use OCP\Group\Events\BeforeGroupDeletedEvent; use OCP\User\Events\BeforeUserDeletedEvent; +use OCP\User\Events\UserDeletedEvent; use Psr\Container\ContainerInterface; class Application extends App implements IBootstrap { @@ -87,6 +91,9 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(RowDeletedEvent::class, WhenRowDeletedAuditLogListener::class); $context->registerEventListener(TableOwnershipTransferredEvent::class, WhenTableTransferredAuditLogListener::class); $context->registerEventListener(AddMissingIndicesEvent::class, AddMissingIndicesListener::class); + $context->registerEventListener(UserDeletedEvent::class, ReceiverCleanupListener::class); + $context->registerEventListener(BeforeGroupDeletedEvent::class, ReceiverCleanupListener::class); + $context->registerEventListener(CircleDestroyedEvent::class, ReceiverCleanupListener::class); $context->registerSearchProvider(SearchTablesProvider::class); diff --git a/lib/Db/ShareMapper.php b/lib/Db/ShareMapper.php index 72f05c7d8e..88f5c327b8 100644 --- a/lib/Db/ShareMapper.php +++ b/lib/Db/ShareMapper.php @@ -250,4 +250,16 @@ public function changeReceiverForNode(string $nodeType, int $nodeId, string $new ->andWhere($qb->expr()->eq('receiver_type', $qb->createNamedParameter('user', IQueryBuilder::PARAM_STR))) ->executeStatement(); } + + + /** + * @throws Exception + */ + public function deleteByReceiver(string $receiver, string $receiverType): int { + $qb = $this->db->getQueryBuilder(); + return $qb->delete($this->table) + ->where($qb->expr()->eq('receiver', $qb->createNamedParameter($receiver, IQueryBuilder::PARAM_STR))) + ->andWhere($qb->expr()->eq('receiver_type', $qb->createNamedParameter($receiverType, IQueryBuilder::PARAM_STR))) + ->executeStatement(); + } } diff --git a/lib/Listener/ReceiverCleanupListener.php b/lib/Listener/ReceiverCleanupListener.php new file mode 100644 index 0000000000..4572ccec83 --- /dev/null +++ b/lib/Listener/ReceiverCleanupListener.php @@ -0,0 +1,54 @@ + */ +class ReceiverCleanupListener implements IEventListener { + public function __construct( + private ShareMapper $shareMapper, + private CirclesManager $circlesManager, + ) { + } + + public function handle(Event $event): void { + if ($event instanceof UserDeletedEvent) { + $this->cleanupByParticipant('user', $event->getUser()->getUID()); + } elseif ($event instanceof BeforeGroupDeletedEvent) { + $this->cleanupGroupShares($event->getGroup()->getGID()); + } elseif ($event instanceof CircleDestroyedEvent) { + $this->cleanupByParticipant('circle', $event->getCircle()->getSingleId()); + } + } + + private function cleanupGroupShares(string $gid): void { + $this->cleanupByParticipant('group', $gid); + + try { + $singleId = $this->circlesManager + ->getFederatedUser($gid, Member::TYPE_GROUP) + ->getSingleId(); + } catch (\Throwable) { + return; + } + + $this->cleanupByParticipant('group', $singleId); + } + + private function cleanupByParticipant(string $type, string $participant): void { + $this->shareMapper->deleteByReceiver($participant, $type); + } +} From ab5eb09352adf31f15efe635f3836be6f070d6ac Mon Sep 17 00:00:00 2001 From: samin-z Date: Wed, 17 Jun 2026 12:09:59 +0200 Subject: [PATCH 2/3] simplify logic Signed-off-by: samin-z --- lib/Db/ShareMapper.php | 1 - lib/Listener/ReceiverCleanupListener.php | 34 ++++++++++-------------- tests/stub.phpstub | 6 +++++ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/lib/Db/ShareMapper.php b/lib/Db/ShareMapper.php index 88f5c327b8..bb59ce7ceb 100644 --- a/lib/Db/ShareMapper.php +++ b/lib/Db/ShareMapper.php @@ -251,7 +251,6 @@ public function changeReceiverForNode(string $nodeType, int $nodeId, string $new ->executeStatement(); } - /** * @throws Exception */ diff --git a/lib/Listener/ReceiverCleanupListener.php b/lib/Listener/ReceiverCleanupListener.php index 4572ccec83..bde1b7e8e1 100644 --- a/lib/Listener/ReceiverCleanupListener.php +++ b/lib/Listener/ReceiverCleanupListener.php @@ -7,48 +7,42 @@ namespace OCA\Tables\Listener; -use OCA\Circles\CirclesManager; use OCA\Circles\Events\CircleDestroyedEvent; -use OCA\Circles\Model\Member; +use OCA\Tables\Constants\ShareReceiverType; use OCA\Tables\Db\ShareMapper; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\Group\Events\BeforeGroupDeletedEvent; use OCP\User\Events\UserDeletedEvent; +use Psr\Log\LoggerInterface; /** @template-implements IEventListener */ class ReceiverCleanupListener implements IEventListener { public function __construct( private ShareMapper $shareMapper, - private CirclesManager $circlesManager, + private LoggerInterface $logger, ) { } public function handle(Event $event): void { if ($event instanceof UserDeletedEvent) { - $this->cleanupByParticipant('user', $event->getUser()->getUID()); + $this->cleanupByParticipant(ShareReceiverType::USER, $event->getUser()->getUID()); } elseif ($event instanceof BeforeGroupDeletedEvent) { - $this->cleanupGroupShares($event->getGroup()->getGID()); + $this->cleanupByParticipant(ShareReceiverType::GROUP, $event->getGroup()->getGID()); } elseif ($event instanceof CircleDestroyedEvent) { - $this->cleanupByParticipant('circle', $event->getCircle()->getSingleId()); + $this->cleanupByParticipant(ShareReceiverType::CIRCLE, $event->getCircle()->getSingleId()); } } - private function cleanupGroupShares(string $gid): void { - $this->cleanupByParticipant('group', $gid); - + private function cleanupByParticipant(string $type, string $participant): void { try { - $singleId = $this->circlesManager - ->getFederatedUser($gid, Member::TYPE_GROUP) - ->getSingleId(); - } catch (\Throwable) { - return; + $this->shareMapper->deleteByReceiver($participant, $type); + } catch (\Throwable $e) { + $this->logger->warning('cleanup table shares for deleted receiver has failed: ' . $e->getMessage(), [ + 'exception' => $e, + 'receiver_type' => $type, + 'receiver' => $participant, + ]); } - - $this->cleanupByParticipant('group', $singleId); - } - - private function cleanupByParticipant(string $type, string $participant): void { - $this->shareMapper->deleteByReceiver($participant, $type); } } diff --git a/tests/stub.phpstub b/tests/stub.phpstub index 800bb6518f..395fc64656 100644 --- a/tests/stub.phpstub +++ b/tests/stub.phpstub @@ -21,6 +21,12 @@ namespace OCA\Circles\Model { } } +namespace OCA\Circles\Events { + class CircleDestroyedEvent extends \OCP\EventDispatcher\Event { + public function getCircle(): \OCA\Circles\Model\Circle {} + } +} + namespace OC\Collaboration\Reference { class LinkReferenceProvider implements IReferenceProvider { abstract public function matchReference(string $referenceText): bool {} From 5a57dc598b2e9728641e5fc79d5a127789e15c9f Mon Sep 17 00:00:00 2001 From: samin-z Date: Wed, 24 Jun 2026 17:43:50 +0200 Subject: [PATCH 3/3] update to use GroupDeletedEvent Signed-off-by: samin-z --- lib/AppInfo/Application.php | 4 ++-- lib/Listener/ReceiverCleanupListener.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index d9cf8e2d93..76c2c2a45c 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -42,7 +42,7 @@ use OCP\Collaboration\Reference\RenderReferenceEvent; use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent; use OCP\DB\Events\AddMissingIndicesEvent; -use OCP\Group\Events\BeforeGroupDeletedEvent; +use OCP\Group\Events\GroupDeletedEvent; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\UserDeletedEvent; use Psr\Container\ContainerInterface; @@ -92,7 +92,7 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(TableOwnershipTransferredEvent::class, WhenTableTransferredAuditLogListener::class); $context->registerEventListener(AddMissingIndicesEvent::class, AddMissingIndicesListener::class); $context->registerEventListener(UserDeletedEvent::class, ReceiverCleanupListener::class); - $context->registerEventListener(BeforeGroupDeletedEvent::class, ReceiverCleanupListener::class); + $context->registerEventListener(GroupDeletedEvent::class, ReceiverCleanupListener::class); $context->registerEventListener(CircleDestroyedEvent::class, ReceiverCleanupListener::class); $context->registerSearchProvider(SearchTablesProvider::class); diff --git a/lib/Listener/ReceiverCleanupListener.php b/lib/Listener/ReceiverCleanupListener.php index bde1b7e8e1..f35213c9b2 100644 --- a/lib/Listener/ReceiverCleanupListener.php +++ b/lib/Listener/ReceiverCleanupListener.php @@ -12,11 +12,11 @@ use OCA\Tables\Db\ShareMapper; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; -use OCP\Group\Events\BeforeGroupDeletedEvent; +use OCP\Group\Events\GroupDeletedEvent; use OCP\User\Events\UserDeletedEvent; use Psr\Log\LoggerInterface; -/** @template-implements IEventListener */ +/** @template-implements IEventListener */ class ReceiverCleanupListener implements IEventListener { public function __construct( private ShareMapper $shareMapper, @@ -27,7 +27,7 @@ public function __construct( public function handle(Event $event): void { if ($event instanceof UserDeletedEvent) { $this->cleanupByParticipant(ShareReceiverType::USER, $event->getUser()->getUID()); - } elseif ($event instanceof BeforeGroupDeletedEvent) { + } elseif ($event instanceof GroupDeletedEvent) { $this->cleanupByParticipant(ShareReceiverType::GROUP, $event->getGroup()->getGID()); } elseif ($event instanceof CircleDestroyedEvent) { $this->cleanupByParticipant(ShareReceiverType::CIRCLE, $event->getCircle()->getSingleId());