diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 4c00c491df..76c2c2a45c 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\GroupDeletedEvent; 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(GroupDeletedEvent::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..bb59ce7ceb 100644 --- a/lib/Db/ShareMapper.php +++ b/lib/Db/ShareMapper.php @@ -250,4 +250,15 @@ 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..f35213c9b2 --- /dev/null +++ b/lib/Listener/ReceiverCleanupListener.php @@ -0,0 +1,48 @@ + */ +class ReceiverCleanupListener implements IEventListener { + public function __construct( + private ShareMapper $shareMapper, + private LoggerInterface $logger, + ) { + } + + public function handle(Event $event): void { + if ($event instanceof UserDeletedEvent) { + $this->cleanupByParticipant(ShareReceiverType::USER, $event->getUser()->getUID()); + } elseif ($event instanceof GroupDeletedEvent) { + $this->cleanupByParticipant(ShareReceiverType::GROUP, $event->getGroup()->getGID()); + } elseif ($event instanceof CircleDestroyedEvent) { + $this->cleanupByParticipant(ShareReceiverType::CIRCLE, $event->getCircle()->getSingleId()); + } + } + + private function cleanupByParticipant(string $type, string $participant): void { + try { + $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, + ]); + } + } +} 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 {}