Skip to content

Commit 88a35a4

Browse files
committed
feat(Capabilities): Expose capabilities
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
1 parent 68e820c commit 88a35a4

4 files changed

Lines changed: 38 additions & 10 deletions

File tree

lib/AppInfo/Application.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace OCA\Bookmarks\AppInfo;
1010

1111
use OCA\Bookmarks\Activity\ActivityPublisher;
12+
use OCA\Bookmarks\Capabilities;
1213
use OCA\Bookmarks\ContextChat\ContextChatProvider;
1314
use OCA\Bookmarks\Dashboard\Frequent;
1415
use OCA\Bookmarks\Dashboard\Recent;
@@ -72,6 +73,8 @@ public function register(IRegistrationContext $context): void {
7273
return $c->get(IRequest::class);
7374
});
7475

76+
$context->registerCapability(Capabilities::class);
77+
7578
$context->registerSearchProvider(Provider::class);
7679
$context->registerDashboardWidget(Recent::class);
7780
$context->registerDashboardWidget(Frequent::class);

lib/Capabilities.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) 2025. The Nextcloud Bookmarks contributors.
5+
*
6+
* This file is licensed under the Affero General Public License version 3 or later. See the COPYING file.
7+
*/
8+
9+
namespace OCA\Bookmarks;
10+
11+
use OCP\Capabilities\IPublicCapability;
12+
13+
class Capabilities implements IPublicCapability {
14+
public function getCapabilities() {
15+
return [
16+
'bookmarks' => [
17+
'javascript-bookmarks' => true,
18+
'hash-functions' => ['xxh32', 'murmur3a', 'sha256'], // ordered by preference
19+
]
20+
];
21+
}
22+
}

lib/Controller/FoldersController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,15 +427,18 @@ public function editFolder(int $folderId, ?string $title = null, ?int $parent_fo
427427
* @PublicPage
428428
* @throws UnauthenticatedError
429429
*/
430-
public function hashFolder(int $folderId, array $fields = ['title', 'url']): JSONResponse {
430+
public function hashFolder(int $folderId, array $fields = ['title', 'url'], string $hashFn = 'sha256'): JSONResponse {
431431
if (!Authorizer::hasPermission(Authorizer::PERM_READ, $this->authorizer->getPermissionsForFolder($folderId, $this->request))) {
432432
$res = new JSONResponse(['status' => 'error', 'data' => ['Could not find folder']], Http::STATUS_BAD_REQUEST);
433433
$res->throttle();
434434
return $res;
435435
}
436+
if (!in_array($hashFn, ['sha256', 'murmur3a', 'xxh32'], true)) {
437+
return new JSONResponse(['status' => 'error', 'data' => ['Unsupported hash function']], Http::STATUS_BAD_REQUEST);
438+
}
436439
try {
437440
$folderId = $this->toInternalFolderId($folderId);
438-
$hash = $this->hashManager->hashFolder($this->authorizer->getUserId(), $folderId, $fields);
441+
$hash = $this->hashManager->hashFolder($this->authorizer->getUserId(), $folderId, $fields, $hashFn);
439442
$res = new JSONResponse(['status' => 'success', 'data' => $hash]);
440443
$res->addHeader('Cache-Control', 'no-cache, must-revalidate');
441444
$res->addHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT');

lib/Service/TreeCacheManager.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ public function invalidateBookmark(int $bookmarkId): void {
181181
* @throws MultipleObjectsReturnedException|\JsonException
182182
* @throws UnsupportedOperation
183183
*/
184-
public function hashFolder($userId, int $folderId, array $fields = ['title', 'url']) : string {
184+
public function hashFolder($userId, int $folderId, array $fields = ['title', 'url'], string $hasFn = 'sha256') : string {
185185
$hash = $this->get(self::CATEGORY_HASH, TreeMapper::TYPE_FOLDER, $folderId);
186-
$selector = $userId . ':' . implode(',', $fields);
186+
$selector = $hasFn . ':' . $userId . ':' . implode(',', $fields);
187187
if (isset($hash[$selector])) {
188188
return $hash[$selector];
189189
}
@@ -198,9 +198,9 @@ public function hashFolder($userId, int $folderId, array $fields = ['title', 'ur
198198
$childHashes = array_map(function ($item) use ($fields, $entity) {
199199
switch ($item['type']) {
200200
case TreeMapper::TYPE_BOOKMARK:
201-
return $this->hashBookmark($item['id'], $fields);
201+
return $this->hashBookmark($item['id'], $fields, $hashFn);
202202
case TreeMapper::TYPE_FOLDER:
203-
return $this->hashFolder($entity->getUserId(), $item['id'], $fields);
203+
return $this->hashFolder($entity->getUserId(), $item['id'], $fields, $hashFn);
204204
default:
205205
throw new UnexpectedValueException('Expected bookmark or folder, but not ' . $item['type']);
206206
}
@@ -212,7 +212,7 @@ public function hashFolder($userId, int $folderId, array $fields = ['title', 'ur
212212
$folder['title'] = $entity->getTitle();
213213
}
214214
$folder['children'] = $childHashes;
215-
$hash[$selector] = hash('sha256', json_encode($folder, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
215+
$hash[$selector] = hash($hashFn, json_encode($folder, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
216216

217217
$this->set(self::CATEGORY_HASH, TreeMapper::TYPE_FOLDER, $folderId, $hash);
218218
return $hash[$selector];
@@ -226,9 +226,9 @@ public function hashFolder($userId, int $folderId, array $fields = ['title', 'ur
226226
* @throws MultipleObjectsReturnedException|\JsonException
227227
* @throws UnsupportedOperation
228228
*/
229-
public function hashBookmark(int $bookmarkId, array $fields = ['title', 'url']): string {
229+
public function hashBookmark(int $bookmarkId, array $fields = ['title', 'url'], string $hashFn = 'sha256'): string {
230230
$hash = $this->get(self::CATEGORY_HASH, TreeMapper::TYPE_BOOKMARK, $bookmarkId);
231-
$selector = implode(',', $fields);
231+
$selector = $hashFn . ':' . implode(',', $fields);
232232
if (isset($hash[$selector])) {
233233
return $hash[$selector];
234234
}
@@ -249,7 +249,7 @@ public function hashBookmark(int $bookmarkId, array $fields = ['title', 'url']):
249249
throw new UnsupportedOperation('Field ' . $field . ' does not exist');
250250
}
251251
}
252-
$hash[$selector] = hash('sha256', json_encode($bookmark, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
252+
$hash[$selector] = hash($hashFn, json_encode($bookmark, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
253253
$this->set(self::CATEGORY_HASH, TreeMapper::TYPE_BOOKMARK, $bookmarkId, $hash);
254254
return $hash[$selector];
255255
}

0 commit comments

Comments
 (0)