Skip to content

Add INodeByPath to Directory - #54441

Merged
sorbaugh merged 2 commits into
masterfrom
fix/directoryAsINodeByPath
Dec 11, 2025
Merged

Add INodeByPath to Directory#54441
sorbaugh merged 2 commits into
masterfrom
fix/directoryAsINodeByPath

Conversation

@salmart-dev

@salmart-devsalmart-dev commented Aug 15, 2025

Copy link
Copy Markdown
Contributor

Summary

Sabre has an interface INodeByPath that allows nodes to fetch a specific node by its path. This was not implemented in our Directory class, leading to any file query to fetch all parent nodes until the file node was reached. This PR makes Directory implement that interface, extends makes the NC Node class extend the Node class from Sabre (required step).

Before:
Screenshot From 2025-08-15 18-52-24

After:
Screenshot From 2025-08-15 18-50-51

Checklist

@salmart-devsalmart-dev self-assigned this Aug 15, 2025
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from cad0ea3 to 87d9b88CompareAugust 15, 2025 16:12
Comment threadapps/dav/lib/Connector/Sabre/Node.php Outdated
Comment threadapps/dav/lib/Connector/Sabre/Node.php Outdated
Comment threadapps/dav/lib/Connector/Sabre/Directory.php Outdated
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from f67982e to c54b5c9CompareAugust 21, 2025 16:28
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from c54b5c9 to cf952ceCompareSeptember 10, 2025 11:02
@github-actions

Copy link
Copy Markdown
Contributor

Possible performance regression detected

Show Output
An unhandled exception has been thrown:
TypeError: array_map(): Argument #2 ($array) must be of type array, null given in /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php:35
Stack trace:
#0 /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php(35): array_map()
#1 /home/runner/work/server/server/3rdparty/symfony/console/Command/Command.php(326): OCAProfilerCommandCompare->execute()
#2 /home/runner/work/server/server/core/Command/Base.php(218): SymfonyComponentConsoleCommandCommand->run()
#3 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(1078): OCCoreCommandBase->run()
#4 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(324): SymfonyComponentConsoleApplication->doRunCommand()
#5 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(175): SymfonyComponentConsoleApplication->doRun()
#6 /home/runner/work/server/server/lib/private/Console/Application.php(187): SymfonyComponentConsoleApplication->run()
#7 /home/runner/work/server/server/console.php(91): OCConsoleApplication->run()
#8 /home/runner/work/server/server/occ(33): require_once('...')
#9 {main}

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Possible performance regression detected

Show Output
An unhandled exception has been thrown:
TypeError: array_map(): Argument #2 ($array) must be of type array, null given in /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php:35
Stack trace:
#0 /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php(35): array_map()
#1 /home/runner/work/server/server/3rdparty/symfony/console/Command/Command.php(326): OCAProfilerCommandCompare->execute()
#2 /home/runner/work/server/server/core/Command/Base.php(218): SymfonyComponentConsoleCommandCommand->run()
#3 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(1078): OCCoreCommandBase->run()
#4 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(324): SymfonyComponentConsoleApplication->doRunCommand()
#5 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(175): SymfonyComponentConsoleApplication->doRun()
#6 /home/runner/work/server/server/lib/private/Console/Application.php(187): SymfonyComponentConsoleApplication->run()
#7 /home/runner/work/server/server/console.php(91): OCConsoleApplication->run()
#8 /home/runner/work/server/server/occ(33): require_once('...')
#9 {main}

@salmart-dev

This comment was marked as outdated.

@salmart-devsalmart-dev added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Sep 10, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Possible performance regression detected

Show Output
An unhandled exception has been thrown:
TypeError: array_map(): Argument #2 ($array) must be of type array, null given in /home/runner/actions-runner/_work/server/server/apps/profiler/lib/Command/Compare.php:35
Stack trace:
#0 /home/runner/actions-runner/_work/server/server/apps/profiler/lib/Command/Compare.php(35): array_map()
#1 /home/runner/actions-runner/_work/server/server/3rdparty/symfony/console/Command/Command.php(326): OCAProfilerCommandCompare->execute()
#2 /home/runner/actions-runner/_work/server/server/core/Command/Base.php(218): SymfonyComponentConsoleCommandCommand->run()
#3 /home/runner/actions-runner/_work/server/server/3rdparty/symfony/console/Application.php(1078): OCCoreCommandBase->run()
#4 /home/runner/actions-runner/_work/server/server/3rdparty/symfony/console/Application.php(324): SymfonyComponentConsoleApplication->doRunCommand()
#5 /home/runner/actions-runner/_work/server/server/3rdparty/symfony/console/Application.php(175): SymfonyComponentConsoleApplication->doRun()
#6 /home/runner/actions-runner/_work/server/server/lib/private/Console/Application.php(187): SymfonyComponentConsoleApplication->run()
#7 /home/runner/actions-runner/_work/server/server/console.php(91): OCConsoleApplication->run()
#8 /home/runner/actions-runner/_work/server/server/occ(33): require_once('...')
#9 {main}

@github-actions

Copy link
Copy Markdown
Contributor

Possible performance regression detected

Show Output
An unhandled exception has been thrown:
TypeError: array_map(): Argument #2 ($array) must be of type array, null given in /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php:35
Stack trace:
#0 /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php(35): array_map()
#1 /home/runner/work/server/server/3rdparty/symfony/console/Command/Command.php(326): OCAProfilerCommandCompare->execute()
#2 /home/runner/work/server/server/core/Command/Base.php(218): SymfonyComponentConsoleCommandCommand->run()
#3 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(1078): OCCoreCommandBase->run()
#4 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(324): SymfonyComponentConsoleApplication->doRunCommand()
#5 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(175): SymfonyComponentConsoleApplication->doRun()
#6 /home/runner/work/server/server/lib/private/Console/Application.php(187): SymfonyComponentConsoleApplication->run()
#7 /home/runner/work/server/server/console.php(91): OCConsoleApplication->run()
#8 /home/runner/work/server/server/occ(33): require_once('...')
#9 {main}

@salmart-dev
salmart-dev marked this pull request as ready for review September 10, 2025 14:04
@salmart-dev
salmart-dev requested a review from a team as a code ownerSeptember 10, 2025 14:04
@salmart-dev
salmart-dev requested review from Altahrim and sorbaugh and removed request for a teamSeptember 10, 2025 14:04
@salmart-devsalmart-dev changed the title Add INodeByPath to Directory [wip]Add INodeByPath to DirectorySep 10, 2025
Comment threadapps/dav/lib/Connector/Sabre/Directory.php
Comment threadconsole.php Outdated
Comment threadapps/dav/lib/Connector/Sabre/Directory.php Outdated
Comment threadconsole.php Outdated
@salmart-dev
salmart-dev marked this pull request as draft September 15, 2025 16:38
@salmart-devsalmart-dev changed the title Add INodeByPath to Directory[WIP] Add INodeByPath to DirectorySep 15, 2025
@salmart-dev

Copy link
Copy Markdown
ContributorAuthor

I converted the PR back to a draft because I ran into an issue with access control rules.

Problem statement

Apps that rely on path navigation to perform checks that block an action could be broken with this PR.

Example

The files_accesscontrol app relies on each node's name to match for names that have been blocked. With this PR, the intermediate nodes in a path may never be navigated to, creating an issue where a file deep in the tree can be accessed, although one of the skipped nodes is marked as not readable through the app.

In the current implementation, the app relies on the fact that isReadable gets called in every Node, which in turn triggers the check for the file name in the app.

How to reproduce

  1. Create a public share
  2. Add a folder inside the public share
  3. Block access to the directory through a flow with the files_accesscontrol app
  4. Try uploading inside the new folder

Uploading should fail but succeeds instead

Possible solution?

Alter files_accesscontrol

For the case in the example, a fix could be to change files_accesscontrol to stop relying on the assumption that all nodes in a path will be navigated to and compare each part of the exploded path with the given value to block, but I fear this would break other flows and checks.


Can someone come up with ideas on how to address this or other things that may break, so that if we try a new solution I can test it still works?

@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from a1a6278 to cf952ceCompareSeptember 16, 2025 08:08
Base automatically changed from refactor/files-sharing to masterNovember 28, 2025 14:43
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch 3 times, most recently from a61556d to 3959a22CompareDecember 2, 2025 10:22
Comment threadapps/dav/lib/Connector/Sabre/Directory.php Outdated
Comment threadapps/dav/lib/Connector/Sabre/Directory.php Outdated
Comment threadapps/dav/lib/Connector/Sabre/Directory.php Outdated
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from 3959a22 to 7ae8463CompareDecember 2, 2025 11:45
@salmart-devsalmart-dev changed the title [WIP] Add INodeByPath to DirectoryAdd INodeByPath to DirectoryDec 2, 2025
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from 7ae8463 to 82e6de7CompareDecember 3, 2025 09:33
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from 82e6de7 to b2b60b5CompareDecember 3, 2025 10:18
@salmart-dev
salmart-dev marked this pull request as ready for review December 3, 2025 10:20
@salmart-dev

Copy link
Copy Markdown
ContributorAuthor

Had to add a check for !$allowDirectory to skip navigating to the parent which is not readable in the context of a file drop (https://github.com/nextcloud/server/pull/54441/files#diff-bbeea4e9faca76aa9e6901242c70df675c85efe25134b50995bbe78109fb636cR559)

cc. @artonge

@salmart-dev

Copy link
Copy Markdown
ContributorAuthor

@icewind1991 this needs another review from you 🙏

The issue with files_accesscontrol has been solved by checking if all parent folders are readable, seems to be working well with group folders as well.

A case that I was expecting to cause trouble with this PR also seems to have the same behaviour on master: within a group folder having a folder with read permissions removed for a specific user, but containing a file with read permissions allowed for the same user. This fails on master and on my PR, so from what I can test, this seems to be working well. The only drawback is that we lose the removal of the N+1 queries for navigating into deep folders, since navigating to the parents to check for readability will load their file infos.

Comment threadapps/dav/lib/Connector/Sabre/Directory.php Outdated
Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com>
Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com>
@salmart-dev
salmart-devforce-pushed the fix/directoryAsINodeByPath branch from b73efca to 871262dCompareDecember 10, 2025 17:31
@sorbaugh
sorbaugh merged commit a7a64de into masterDec 11, 2025
282 of 308 checks passed
@sorbaugh
sorbaugh deleted the fix/directoryAsINodeByPath branch December 11, 2025 13:07
nickvergessen added a commit to nextcloud/files_accesscontrol that referenced this pull request Dec 15, 2025
Signed-off-by: Joas Schilling <coding@schilljs.com>
nickvergessen added a commit to nextcloud/files_accesscontrol that referenced this pull request Dec 15, 2025
Signed-off-by: Joas Schilling <coding@schilljs.com>
nickvergessen added a commit to nextcloud/files_accesscontrol that referenced this pull request Dec 15, 2025
@salmart-devsalmart-dev mentioned this pull request Dec 22, 2025
7 tasks
@nextcloud-botnextcloud-bot mentioned this pull request Jan 6, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to reviewWaiting for reviewsperformance 🚀

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@salmart-dev@icewind1991@artonge@CarlSchwan@come-nc@sorbaugh