浏览代码

feat: support readdir for directory symlinks

KernelDeimos 7 月之前
父节点
当前提交
7f1b870d30

+ 13 - 2
src/backend/src/filesystem/hl_operations/hl_readdir.js

@@ -18,7 +18,7 @@
  */
 const APIError = require("../../api/APIError");
 const { chkperm } = require("../../helpers");
-const { TYPE_DIRECTORY } = require("../FSNodeContext");
+const { TYPE_DIRECTORY, TYPE_SYMLINK } = require("../FSNodeContext");
 const { LLListUsers } = require("../ll_operations/ll_listusers");
 const { LLReadDir } = require("../ll_operations/ll_readdir");
 const { LLReadShares } = require("../ll_operations/ll_readshares");
@@ -26,12 +26,23 @@ const { HLFilesystemOperation } = require("./definitions");
 
 class HLReadDir extends HLFilesystemOperation {
     async _run () {
-        const { subject, user, no_thumbs, no_assocs, actor } = this.values;
+        const { subject: subject_let, user, no_thumbs, no_assocs, actor } = this.values;
+        let subject = subject_let;
 
         if ( ! await subject.exists() ) {
             throw APIError.create('subject_does_not_exist');
         }
 
+        if ( await subject.get('type') === TYPE_SYMLINK ) {
+            const { context } = this;
+            const svc_acl = context.get('services').get('acl');
+            if ( ! await svc_acl.check(actor, subject, 'read') ) {
+                throw await svc_acl.get_safe_acl_error(actor, subject, 'read');
+            }
+            const target = await subject.getTarget();
+            subject = target;
+        }
+
         if ( await subject.get('type') !== TYPE_DIRECTORY ) {
             const { context } = this;
             const svc_acl = context.get('services').get('acl');

+ 15 - 1
src/backend/src/filesystem/ll_operations/ll_readdir.js

@@ -17,6 +17,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 const APIError = require("../../api/APIError");
+const { TYPE_SYMLINK } = require("../FSNodeContext");
 const { RootNodeSelector } = require("../node/selectors");
 const { NodeUIDSelector, NodeChildSelector } = require("../node/selectors");
 const { LLFilesystemOperation } = require("./definitions");
@@ -24,7 +25,8 @@ const { LLFilesystemOperation } = require("./definitions");
 class LLReadDir extends LLFilesystemOperation {
     async _run () {
         const { context } = this;
-        const { subject, user, actor, no_acl } = this.values;
+        const { subject: subject_let, user, actor, no_acl } = this.values;
+        let subject = subject_let;
 
         if ( ! await subject.exists() ) {
             throw APIError.create('subject_does_not_exist');
@@ -37,6 +39,18 @@ class LLReadDir extends LLFilesystemOperation {
             }
         }
 
+        // TODO: DRY ACL check here
+        const subject_type = await subject.get('type');
+        if ( subject_type === TYPE_SYMLINK ) {
+            const target = await subject.getTarget();
+            if ( ! no_acl ) {
+                if ( ! await svc_acl.check(actor, target, 'list') ) {
+                    throw await svc_acl.get_safe_acl_error(actor, target, 'list');
+                }
+            }
+            subject = target;
+        }
+
         const subject_uuid = await subject.get('uid');
 
         const svc = context.get('services');