From 1c381c7529e23fe35d905cf2ba640ae15ff5fc00 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Sat, 24 Jul 2021 14:12:17 +0200 Subject: [PATCH] Fix hash endpoint: Allow hashing with tags fixes #1606 Signed-off-by: Marcel Klehr --- lib/Controller/FoldersController.php | 4 +++ lib/Service/TreeCacheManager.php | 23 +++++++++++-- tests/FolderControllerTest.php | 49 ++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/lib/Controller/FoldersController.php b/lib/Controller/FoldersController.php index 40b54afb..0cbfcb71 100644 --- a/lib/Controller/FoldersController.php +++ b/lib/Controller/FoldersController.php @@ -382,6 +382,10 @@ class FoldersController extends ApiController { return new JSONResponse(['status' => 'error', 'data' => 'Could not find folder'], Http::STATUS_BAD_REQUEST); } catch (MultipleObjectsReturnedException $e) { return new JSONResponse(['status' => 'error', 'data' => 'Multiple objects found'], Http::STATUS_BAD_REQUEST); + } catch (\JsonException $e) { + return new JSONResponse(['status' => 'error', 'data' => 'Could not find folder'], Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (UnsupportedOperation $e) { + return new JSONResponse(['status' => 'error', 'data' => 'Unsupported operation: '.$e->getMessage()], Http::STATUS_BAD_REQUEST); } } diff --git a/lib/Service/TreeCacheManager.php b/lib/Service/TreeCacheManager.php index efa6e62b..fe609026 100644 --- a/lib/Service/TreeCacheManager.php +++ b/lib/Service/TreeCacheManager.php @@ -15,6 +15,7 @@ use OCA\Bookmarks\Db\TreeMapper; use OCA\Bookmarks\Db\Folder; use OCA\Bookmarks\Events\ChangeEvent; use OCA\Bookmarks\Events\MoveEvent; +use OCA\Bookmarks\Exception\UnsupportedOperation; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\IAppContainer; @@ -64,6 +65,10 @@ class TreeCacheManager implements IEventListener { * @var IAppContainer */ private $appContainer; + /** + * @var \OCA\Bookmarks\Db\TagMapper + */ + private $tagMapper; /** * FolderMapper constructor. @@ -74,8 +79,9 @@ class TreeCacheManager implements IEventListener { * @param SharedFolderMapper $sharedFolderMapper * @param ICacheFactory $cacheFactory * @param IAppContainer $appContainer + * @param \OCA\Bookmarks\Db\TagMapper $tagMapper */ - public function __construct(FolderMapper $folderMapper, BookmarkMapper $bookmarkMapper, ShareMapper $shareMapper, SharedFolderMapper $sharedFolderMapper, ICacheFactory $cacheFactory, IAppContainer $appContainer) { + public function __construct(FolderMapper $folderMapper, BookmarkMapper $bookmarkMapper, ShareMapper $shareMapper, SharedFolderMapper $sharedFolderMapper, ICacheFactory $cacheFactory, IAppContainer $appContainer, \OCA\Bookmarks\Db\TagMapper $tagMapper) { $this->folderMapper = $folderMapper; $this->bookmarkMapper = $bookmarkMapper; $this->shareMapper = $shareMapper; @@ -86,6 +92,7 @@ class TreeCacheManager implements IEventListener { $this->caches[self::CATEGORY_CHILDREN] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_CHILDREN); $this->caches[self::CATEGORY_CHILDORDER] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_CHILDORDER); $this->appContainer = $appContainer; + $this->tagMapper = $tagMapper; } @@ -185,8 +192,9 @@ class TreeCacheManager implements IEventListener { * @return string * @throws DoesNotExistException * @throws MultipleObjectsReturnedException|\JsonException + * @throws UnsupportedOperation */ - public function hashFolder($userId, int $folderId, $fields = ['title', 'url']) : string { + public function hashFolder($userId, int $folderId, array $fields = ['title', 'url']) : string { $hash = $this->get(self::CATEGORY_HASH, TreeMapper::TYPE_FOLDER, $folderId); $selector = $userId . ':' . implode(',', $fields); if (isset($hash[$selector])) { @@ -229,6 +237,7 @@ class TreeCacheManager implements IEventListener { * @return string * @throws DoesNotExistException * @throws MultipleObjectsReturnedException|\JsonException + * @throws UnsupportedOperation */ public function hashBookmark(int $bookmarkId, array $fields = ['title', 'url']): string { $hash = $this->get(self::CATEGORY_HASH, TreeMapper::TYPE_BOOKMARK, $bookmarkId); @@ -243,7 +252,15 @@ class TreeCacheManager implements IEventListener { $entity = $this->bookmarkMapper->find($bookmarkId); $bookmark = []; foreach ($fields as $field) { - $bookmark[$field] = $entity->{'get' . $field}(); + if ($field === 'tags') { + $bookmark[$field] = $this->tagMapper->findByBookmark($bookmarkId); + continue; + } + try { + $bookmark[$field] = $entity->{'get' . $field}(); + } catch (\BadFunctionCallException $e) { + throw new UnsupportedOperation('Field '.$field.' does not exist'); + } } $hash[$selector] = hash('sha256', json_encode($bookmark, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); $this->set(self::CATEGORY_HASH, TreeMapper::TYPE_BOOKMARK, $bookmarkId, $hash); diff --git a/tests/FolderControllerTest.php b/tests/FolderControllerTest.php index a5889469..cbbed083 100644 --- a/tests/FolderControllerTest.php +++ b/tests/FolderControllerTest.php @@ -300,6 +300,55 @@ class FolderControllerTest extends TestCase { $this->assertEquals($this->folder1->getTitle(), $data['item']['title']); } + /** + * @throws AlreadyExistsError + * @throws UrlParseError + * @throws UserLimitExceededError + * @throws \OCP\AppFramework\Db\DoesNotExistException + * @throws MultipleObjectsReturnedException + */ + public function testHash(): void { + $this->cleanUp(); + $this->setupBookmarks(); + $this->authorizer->setUserId($this->userId); + + // get hash for title,url + $output = $this->controller->hashFolder(-1); + $data1 = $output->getData(); + $this->assertEquals('success', $data1['status'], var_export($data1, true)); + + // get hash for title,url,tags + $output = $this->controller->hashFolder(-1, ['title', 'url', 'tags']); + $data2 = $output->getData(); + $this->assertEquals('success', $data2['status'], var_export($data2, true)); + + $this->assertNotEquals($data2['data'], $data1['data']); + + // change sub folder + $output = $this->controller->editFolder($this->folder1->getId(), 'blabla'); + $data = $output->getData(); + $this->assertEquals('success', $data['status'], var_export($data, true)); + + // get hash for title,url + $output = $this->controller->hashFolder(-1); + $data1New = $output->getData(); + $this->assertEquals('success', $data1New['status'], var_export($data1New, true)); + + // get hash for title,url,tags + $output = $this->controller->hashFolder(-1, ['title', 'url', 'tags']); + $data2New = $output->getData(); + $this->assertEquals('success', $data2New['status'], var_export($data2New, true)); + + $this->assertNotEquals($data1New['data'], $data1['data']); + $this->assertNotEquals($data2New['data'], $data2['data']); + $this->assertNotEquals($data1New['data'], $data2New['data']); + + // check fail + $output = $this->controller->hashFolder(-1, ['title', 'url', 'foo']); + $data3 = $output->getData(); + $this->assertEquals('error', $data3['status'], var_export($data3, true)); + } + /** * @throws AlreadyExistsError * @throws UrlParseError