|
7 | 7 | */ |
8 | 8 | namespace OCA\Files\Controller; |
9 | 9 |
|
| 10 | +use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException; |
10 | 11 | use OC\Files\Node\Node; |
| 12 | +use OC\Files\Search\SearchComparison; |
| 13 | +use OC\Files\Search\SearchQuery; |
| 14 | +use OCA\Files\ResponseDefinitions; |
11 | 15 | use OCA\Files\Service\TagService; |
12 | 16 | use OCA\Files\Service\UserConfig; |
13 | 17 | use OCA\Files\Service\ViewConfig; |
14 | 18 | use OCP\AppFramework\Controller; |
15 | 19 | use OCP\AppFramework\Http; |
| 20 | +use OCP\AppFramework\Http\Attribute\ApiRoute; |
16 | 21 | use OCP\AppFramework\Http\Attribute\NoAdminRequired; |
17 | 22 | use OCP\AppFramework\Http\Attribute\NoCSRFRequired; |
18 | 23 | use OCP\AppFramework\Http\Attribute\OpenAPI; |
|
24 | 29 | use OCP\AppFramework\Http\JSONResponse; |
25 | 30 | use OCP\AppFramework\Http\Response; |
26 | 31 | use OCP\AppFramework\Http\StreamResponse; |
| 32 | +use OCP\Files\Cache\ICacheEntry; |
27 | 33 | use OCP\Files\File; |
28 | 34 | use OCP\Files\Folder; |
| 35 | +use OCP\Files\IRootFolder; |
29 | 36 | use OCP\Files\NotFoundException; |
| 37 | +use OCP\Files\Search\ISearchComparison; |
30 | 38 | use OCP\IConfig; |
| 39 | +use OCP\IL10N; |
31 | 40 | use OCP\IPreview; |
32 | 41 | use OCP\IRequest; |
| 42 | +use OCP\IUser; |
33 | 43 | use OCP\IUserSession; |
34 | 44 | use OCP\Share\IManager; |
35 | 45 | use OCP\Share\IShare; |
| 46 | +use Psr\Log\LoggerInterface; |
| 47 | +use Throwable; |
36 | 48 |
|
37 | 49 | /** |
| 50 | + * @psalm-import-type FilesFolderTree from ResponseDefinitions |
| 51 | + * |
38 | 52 | * @package OCA\Files\Controller |
39 | 53 | */ |
40 | 54 | class ApiController extends Controller { |
41 | | - private TagService $tagService; |
42 | | - private IManager $shareManager; |
43 | | - private IPreview $previewManager; |
44 | | - private IUserSession $userSession; |
45 | | - private IConfig $config; |
46 | | - private ?Folder $userFolder; |
47 | | - private UserConfig $userConfig; |
48 | | - private ViewConfig $viewConfig; |
49 | | - |
50 | 55 | public function __construct(string $appName, |
51 | 56 | IRequest $request, |
52 | | - IUserSession $userSession, |
53 | | - TagService $tagService, |
54 | | - IPreview $previewManager, |
55 | | - IManager $shareManager, |
56 | | - IConfig $config, |
57 | | - ?Folder $userFolder, |
58 | | - UserConfig $userConfig, |
59 | | - ViewConfig $viewConfig) { |
| 57 | + private IUserSession $userSession, |
| 58 | + private TagService $tagService, |
| 59 | + private IPreview $previewManager, |
| 60 | + private IManager $shareManager, |
| 61 | + private IConfig $config, |
| 62 | + private ?Folder $userFolder, |
| 63 | + private UserConfig $userConfig, |
| 64 | + private ViewConfig $viewConfig, |
| 65 | + private IL10N $l10n, |
| 66 | + private IRootFolder $rootFolder, |
| 67 | + private LoggerInterface $logger, |
| 68 | + ) { |
60 | 69 | parent::__construct($appName, $request); |
61 | | - $this->userSession = $userSession; |
62 | | - $this->tagService = $tagService; |
63 | | - $this->previewManager = $previewManager; |
64 | | - $this->shareManager = $shareManager; |
65 | | - $this->config = $config; |
66 | | - $this->userFolder = $userFolder; |
67 | | - $this->userConfig = $userConfig; |
68 | | - $this->viewConfig = $viewConfig; |
69 | 70 | } |
70 | 71 |
|
71 | 72 | /** |
@@ -232,6 +233,77 @@ public function getRecentFiles() { |
232 | 233 | return new DataResponse(['files' => $files]); |
233 | 234 | } |
234 | 235 |
|
| 236 | + /** |
| 237 | + * @param Folder[] $folders |
| 238 | + */ |
| 239 | + private function getTree(array $folders): array { |
| 240 | + $user = $this->userSession->getUser(); |
| 241 | + if (!($user instanceof IUser)) { |
| 242 | + throw new NotLoggedInException(); |
| 243 | + } |
| 244 | + |
| 245 | + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); |
| 246 | + $tree = []; |
| 247 | + foreach ($folders as $folder) { |
| 248 | + $path = $userFolder->getRelativePath($folder->getPath()); |
| 249 | + if ($path === null) { |
| 250 | + continue; |
| 251 | + } |
| 252 | + $pathBasenames = explode('/', trim($path, '/')); |
| 253 | + $current = &$tree; |
| 254 | + foreach ($pathBasenames as $basename) { |
| 255 | + if (!isset($current['children'][$basename])) { |
| 256 | + $current['children'][$basename] = [ |
| 257 | + 'id' => $folder->getId(), |
| 258 | + ]; |
| 259 | + $displayName = $folder->getName(); |
| 260 | + if ($displayName !== $basename) { |
| 261 | + $current['children'][$basename]['displayName'] = $displayName; |
| 262 | + } |
| 263 | + } |
| 264 | + $current = &$current['children'][$basename]; |
| 265 | + } |
| 266 | + } |
| 267 | + return $tree['children'] ?? $tree; |
| 268 | + } |
| 269 | + |
| 270 | + /** |
| 271 | + * Returns the folder tree of the user |
| 272 | + * |
| 273 | + * @return JSONResponse<Http::STATUS_OK, FilesFolderTree, array{}>|JSONResponse<Http::STATUS_UNAUTHORIZED, array{message: string}, array{}> |
| 274 | + * |
| 275 | + * 200: Folder tree returned successfully |
| 276 | + * 401: Unauthorized |
| 277 | + */ |
| 278 | + #[NoAdminRequired] |
| 279 | + #[ApiRoute(verb: 'GET', url: '/api/v1/folder-tree')] |
| 280 | + public function getFolderTree(): JSONResponse { |
| 281 | + $user = $this->userSession->getUser(); |
| 282 | + if (!($user instanceof IUser)) { |
| 283 | + return new JSONResponse([ |
| 284 | + 'message' => $this->l10n->t('Failed to authorize'), |
| 285 | + ], Http::STATUS_UNAUTHORIZED); |
| 286 | + } |
| 287 | + |
| 288 | + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); |
| 289 | + try { |
| 290 | + $searchQuery = new SearchQuery( |
| 291 | + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', ICacheEntry::DIRECTORY_MIMETYPE), |
| 292 | + 0, |
| 293 | + 0, |
| 294 | + [], |
| 295 | + $user, |
| 296 | + false, |
| 297 | + ); |
| 298 | + /** @var Folder[] $folders */ |
| 299 | + $folders = $userFolder->search($searchQuery); |
| 300 | + $tree = $this->getTree($folders); |
| 301 | + } catch (Throwable $th) { |
| 302 | + $this->logger->error($th->getMessage(), ['exception' => $th]); |
| 303 | + $tree = []; |
| 304 | + } |
| 305 | + return new JSONResponse($tree, Http::STATUS_OK, [], JSON_FORCE_OBJECT); |
| 306 | + } |
235 | 307 |
|
236 | 308 | /** |
237 | 309 | * Returns the current logged-in user's storage stats. |
|
0 commit comments