diff --git a/src/backend/controllers/fs/FSController.ts b/src/backend/controllers/fs/FSController.ts index d2b678d8b..3db7e81bb 100644 --- a/src/backend/controllers/fs/FSController.ts +++ b/src/backend/controllers/fs/FSController.ts @@ -1110,7 +1110,6 @@ export class FSController extends PuterController { const rootChildren = await listRootEntries( actor, this.stores.fsEntry, - this.services.permission, ); const rootSuggestions = await this.services.suggestedApps.getSuggestedAppsForEntries( diff --git a/src/backend/controllers/fs/LegacyFSController.ts b/src/backend/controllers/fs/LegacyFSController.ts index 2d8ae6dfc..6fbe18c50 100644 --- a/src/backend/controllers/fs/LegacyFSController.ts +++ b/src/backend/controllers/fs/LegacyFSController.ts @@ -484,7 +484,6 @@ export class LegacyFSController extends PuterController { const rootChildren = await listRootEntries( actor, this.stores.fsEntry, - this.services.permission, ); const rootSuggestions = await this.services.suggestedApps.getSuggestedAppsForEntries( diff --git a/src/backend/services/fs/rootListing.test.ts b/src/backend/services/fs/rootListing.test.ts index 59614f128..7d866d0c9 100644 --- a/src/backend/services/fs/rootListing.test.ts +++ b/src/backend/services/fs/rootListing.test.ts @@ -66,8 +66,7 @@ const makeUser = async () => { return { userId: created.id, username, actor }; }; -const listFor = (actor: Actor) => - listRootEntries(actor, fsEntryStore, permissionService); +const listFor = (actor: Actor) => listRootEntries(actor, fsEntryStore); describe('listRootEntries', () => { it('shows the actor their own home directory, exactly once', async () => { @@ -91,7 +90,7 @@ describe('listRootEntries', () => { ); }); - it('adds the home of every user who has granted the actor a permission', async () => { + it('leaves an issuer’s home out of root when only a file was shared', async () => { const holder = await makeUser(); const issuer = await makeUser(); const shared = (await fsEntryStore.getEntryByPath( @@ -105,9 +104,11 @@ describe('listRootEntries', () => { const entries = await listFor(holder.actor); - expect(entries.map((entry) => entry.path).sort()).toEqual( - [`/${holder.username}`, `/${issuer.username}`].sort(), - ); + // Listing it here would advertise a folder readdir then refuses to + // open: the grant is on Documents, which says nothing about its parent. + expect(entries.map((entry) => entry.path)).toEqual([ + `/${holder.username}`, + ]); }); it('heals a home row whose path drifted from the username', async () => { diff --git a/src/backend/services/fs/rootListing.ts b/src/backend/services/fs/rootListing.ts index 43caf0cb8..47cb4d1a9 100644 --- a/src/backend/services/fs/rootListing.ts +++ b/src/backend/services/fs/rootListing.ts @@ -20,19 +20,18 @@ import type { Actor } from '../../core/actor.js'; import type { FSEntry } from '../../stores/fs/FSEntry.js'; import type { FSEntryStore } from '../../stores/fs/FSEntryStore.js'; -import type { PermissionService } from '../permission/PermissionService.js'; /** * Synthesize the listing for the virtual root `/`. There is no fsentry row at - * `/` — instead root is a virtual aggregate of user-directory entries the actor - * can see: the actor's own home plus any other users' homes granted via - * permission issuers (i.e. users that have shared something with this actor). - * Mirrors v1's `LLListUsers`. + * `/` — root stands in for the actor's own home. + * + * Issuer homes are deliberately absent: a grant on a file says nothing about + * its ancestors, so listing them advertised folders `readdir` then refused to + * open. Shares are reached through the sharing API instead. */ export async function listRootEntries( actor: Actor, fsEntryStore: FSEntryStore, - permissionService: PermissionService, ): Promise { const entries: FSEntry[] = []; const seenPaths = new Set(); @@ -69,15 +68,5 @@ export async function listRootEntries( await pushByUsername(actor.user.username); - if (typeof userId === 'number') { - const issuers = await permissionService.listUserPermissionIssuers({ - id: userId, - }); - for (const issuer of issuers) { - if (!issuer) continue; - await pushByUsername(issuer.username); - } - } - return entries; }