diff --git a/packages/backend/src/filesystem/hl_operations/hl_readdir.js b/packages/backend/src/filesystem/hl_operations/hl_readdir.js index 7b8c41394..412a3f626 100644 --- a/packages/backend/src/filesystem/hl_operations/hl_readdir.js +++ b/packages/backend/src/filesystem/hl_operations/hl_readdir.js @@ -20,6 +20,7 @@ const APIError = require("../../api/APIError"); const { chkperm } = require("../../helpers"); const { TYPE_DIRECTORY } = require("../FSNodeContext"); const { LLReadDir } = require("../ll_operations/ll_readdir"); +const { LLReadShares } = require("../ll_operations/ll_readshares"); const { HLFilesystemOperation } = require("./definitions"); class HLReadDir extends HLFilesystemOperation { @@ -38,9 +39,26 @@ class HLReadDir extends HLFilesystemOperation { } return [subject]; } + + let children; - const ll_readdir = new LLReadDir(); - const children = await ll_readdir.run(this.values); + this.log.noticeme('READDIR', + { + userdir: await subject.isUserDirectory(), + namediff: await subject.get('name') !== user.username + } + ); + if ( + await subject.isUserDirectory() && + await subject.get('name') !== user.username + ) { + this.log.noticeme('THIS HAPPEN'); + const ll_readshares = new LLReadShares(); + children = await ll_readshares.run(this.values); + } else { + const ll_readdir = new LLReadDir(); + children = await ll_readdir.run(this.values); + } return Promise.all(children.map(async child => { // await child.fetchAll(null, user); diff --git a/packages/backend/src/filesystem/ll_operations/ll_readdir.js b/packages/backend/src/filesystem/ll_operations/ll_readdir.js index 545460a28..288f305eb 100644 --- a/packages/backend/src/filesystem/ll_operations/ll_readdir.js +++ b/packages/backend/src/filesystem/ll_operations/ll_readdir.js @@ -24,15 +24,17 @@ const { LLFilesystemOperation } = require("./definitions"); class LLReadDir extends LLFilesystemOperation { async _run () { const { context } = this; - const { subject, user, actor } = this.values; + const { subject, user, actor, no_acl } = this.values; if ( ! await subject.exists() ) { throw APIError.create('subject_does_not_exist'); } const svc_acl = context.get('services').get('acl'); - if ( ! await svc_acl.check(actor, subject, 'list') ) { - throw await svc_acl.get_safe_acl_error(actor, subject, 'list'); + if ( ! no_acl ) { + if ( ! await svc_acl.check(actor, subject, 'list') ) { + throw await svc_acl.get_safe_acl_error(actor, subject, 'list'); + } } const subject_uuid = await subject.get('uid'); diff --git a/packages/backend/src/filesystem/ll_operations/ll_readshares.js b/packages/backend/src/filesystem/ll_operations/ll_readshares.js new file mode 100644 index 000000000..03fe4acec --- /dev/null +++ b/packages/backend/src/filesystem/ll_operations/ll_readshares.js @@ -0,0 +1,68 @@ +const { Context } = require("../../util/context"); +const { TYPE_DIRECTORY } = require("../FSNodeContext"); +const { LLFilesystemOperation } = require("./definitions"); +const { LLReadDir } = require("./ll_readdir"); + +class LLReadShares extends LLFilesystemOperation { + static description = ` + Obtain the highest-level entries under this directory + for which the current actor has at least "see" permission. + + This is a breadth-first search. When any node is + found with "see" permission is found, children of that node + will not be traversed. + `; + + async _run () { + const results = []; + await this.recursive_part(results, this.values); + + return results; + } + + async recursive_part (results, { subject, user, actor }) { + actor = actor || Context.get('actor'); + const ll_readdir = new LLReadDir(); + const children = await ll_readdir.run({ + subject, user, + no_thumbs: true, + no_assocs: true, + no_acl: true, + }); + + const svc = Context.get('services'); + const svc_acl = svc.get('acl'); + + const promises = []; + + for ( const child of children ) { + // If we have at least see permission: terminal node + const acl_result = await svc_acl.check(actor, child, 'see'); + console.log( + '\x1B[31;1mWHAT DIS?\x1B[0m', + actor, + child.entry?.path, + child.selectors_[0].describe(), + acl_result, + ) + if ( acl_result ) { + results.push(child); + continue; + } + + if ( await child.get('type') !== TYPE_DIRECTORY ) { + continue; + } + + const p = this.recursive_part(results, { + subject: child, user }); + promises.push(p); + } + + await Promise.all(promises); + } +} + +module.exports = { + LLReadShares, +};