From 2f213eea9f6376dd9efb92da4e957a16354da7b8 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Tue, 26 Nov 2024 18:39:50 -0300 Subject: [PATCH] fix: prevent don't delete file when folder is deleted When we delete the LibreSign folder and remove from trash, is necessary to delete LibreSign files too Signed-off-by: Vitor Mattos --- lib/AppInfo/Application.php | 2 + lib/Listener/BeforeNodeDeletedListener.php | 47 ++++++++++--------- src/Components/Request/VisibleElements.vue | 5 +- .../AEnvironmentPageAwareControllerTest.php | 5 +- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 5a64908f61..a12a3b9f96 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -29,6 +29,7 @@ use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Cache\CacheEntryRemovedEvent; use OCP\Files\Events\Node\BeforeNodeDeletedEvent; use OCP\User\Events\UserDeletedEvent; @@ -59,6 +60,7 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class); $context->registerEventListener(BeforeNodeDeletedEvent::class, BeforeNodeDeletedListener::class); + $context->registerEventListener(CacheEntryRemovedEvent::class, BeforeNodeDeletedListener::class); $context->registerEventListener(SignedEvent::class, SignedListener::class); // Files newFile listener diff --git a/lib/Listener/BeforeNodeDeletedListener.php b/lib/Listener/BeforeNodeDeletedListener.php index ca303f8839..fc242e2cf4 100644 --- a/lib/Listener/BeforeNodeDeletedListener.php +++ b/lib/Listener/BeforeNodeDeletedListener.php @@ -14,12 +14,13 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\Files\Cache\CacheEntryRemovedEvent; use OCP\Files\Events\Node\BeforeNodeDeletedEvent; use OCP\Files\File; use OCP\IDBConnection; /** - * @template-implements IEventListener + * @template-implements IEventListener */ class BeforeNodeDeletedListener implements IEventListener { public function __construct( @@ -30,17 +31,25 @@ public function __construct( } public function handle(Event $event): void { - if (!$event instanceof BeforeNodeDeletedEvent) { + if ($event instanceof BeforeNodeDeletedEvent) { + $node = $event->getNode(); + if (!$node instanceof File) { + return; + } + if (!in_array($node->getMimeType(), ValidateHelper::VALID_MIMETIPE)) { + return; + } + $nodeId = $node->getId(); + $this->delete($nodeId); return; } - $node = $event->getNode(); - if (!$node instanceof File) { - return; - } - if (!in_array($node->getMimeType(), ValidateHelper::VALID_MIMETIPE)) { - return; + if ($event instanceof CacheEntryRemovedEvent) { + $this->delete($event->getFileId()); } - $nodeId = $node->getId(); + return; + } + + private function delete(int $nodeId): void { $type = $this->fileMapper->getFileType($nodeId); if ($type === 'not_libresign_file') { return; @@ -53,24 +62,16 @@ public function handle(Event $event): void { break; case 'file': $libresignFile = $this->fileMapper->getByFileId($nodeId); - if ($libresignFile->getStatus() === $libresignFile::STATUS_SIGNED) { - $libresignFile->setNodeId(null); - $this->fileMapper->update($libresignFile); - break; - } $this->requestSignatureService->deleteRequestSignature(['file' => ['fileId' => $nodeId]]); + $this->fileMapper->delete($libresignFile); break; case 'user_element': case 'file_element': - $this->deleteByType($nodeId, $type); + $field = $type === 'file' ? 'node_id' : 'file_id'; + $qb = $this->db->getQueryBuilder(); + $qb->delete('libresign_' . $type) + ->where($qb->expr()->eq($field, $qb->createNamedParameter($nodeId, IQueryBuilder::PARAM_INT))) + ->executeStatement(); } } - - private function deleteByType(int $nodeId, string $type): void { - $field = $type === 'file' ? 'node_id' : 'file_id'; - $qb = $this->db->getQueryBuilder(); - $qb->delete('libresign_' . $type) - ->where($qb->expr()->eq($field, $qb->createNamedParameter($nodeId, IQueryBuilder::PARAM_INT))) - ->executeStatement(); - } } diff --git a/src/Components/Request/VisibleElements.vue b/src/Components/Request/VisibleElements.vue index dad044cd58..1a35eb654d 100644 --- a/src/Components/Request/VisibleElements.vue +++ b/src/Components/Request/VisibleElements.vue @@ -260,8 +260,11 @@ export default { })) }, async goToSign() { + // after save, the document is no more acessible by this way, + // this is the reason to retain the UUID before save action + const uuid = this.document.settings.signerFileUuid if (await this.save()) { - const route = this.$router.resolve({ name: 'SignPDF', params: { uuid: this.document.settings.signerFileUuid } }) + const route = this.$router.resolve({ name: 'SignPDF', params: { uuid } }) window.location.href = route.href } }, diff --git a/tests/Unit/Controller/AEnvironmentPageAwareControllerTest.php b/tests/Unit/Controller/AEnvironmentPageAwareControllerTest.php index 8aa8a33a3c..a56f8a16c8 100644 --- a/tests/Unit/Controller/AEnvironmentPageAwareControllerTest.php +++ b/tests/Unit/Controller/AEnvironmentPageAwareControllerTest.php @@ -97,10 +97,9 @@ public function testLoadFileUuidWhenFileNotFound(): void { $this->expectExceptionCode(404); $this->expectExceptionMessage(json_encode([ 'action' => 2000, - 'errors' => ['File not found'], + 'errors' => ['Invalid UUID'], ])); - $signers = $this->getSignersFromFileId($file->getId()); - $this->controller->loadNextcloudFileFromSignRequestUuid($signers[0]->getUuid()); + $this->controller->validateSignRequestUuid($file->getUuid()); } }