Fix hash endpoint: Allow hashing with tags

fixes #1606

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
Marcel Klehr 2021-07-24 14:12:17 +02:00
parent 5ca40abef9
commit 1c381c7529
3 changed files with 73 additions and 3 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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