From 10256569f3acab959fdeeaccc88b3f6301403e28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philipp=20Sch=C3=BCttl=C3=B6ffel?=
 <schuettloeffel@zqs.uni-hannover.de>
Date: Mon, 17 Jun 2024 06:59:12 +0000
Subject: [PATCH] Resolve "Selbst hochgeladene Dateien in Ordnern ohne
 Lesezugriff schlecht sichtbar"

Closes #2954

Merge request studip/studip!1997
---
 .../Routes/Files/RangeFileRefsIndex.php       |  2 +-
 .../JsonApi/Routes/Files/SubfilerefsIndex.php | 11 ++++++--
 lib/classes/JsonApi/Schemas/File.php          |  2 +-
 lib/classes/JsonApi/Schemas/Folder.php        | 12 ++++++++-
 lib/filesystem/HomeworkFolder.php             | 26 ++++++++++++++++---
 lib/filesystem/PermissionEnabledFolder.php    | 23 +++++++++++++++-
 lib/filesystem/TimedFolder.php                | 21 ++++++++++-----
 .../homework_folder/description.php           |  9 +------
 .../filesystem/timed_folder/description.php   | 11 --------
 9 files changed, 81 insertions(+), 36 deletions(-)

diff --git a/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php b/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php
index 8f69d6abec0..773071e341d 100644
--- a/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php
+++ b/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php
@@ -13,7 +13,7 @@ class RangeFileRefsIndex extends AbstractRangeIndex
 
         $filerefs = [];
         foreach ($filesAndFolders['files'] as $file_object) {
-            if (method_exists($file_object, "getFileRef")) {
+            if (method_exists($file_object, 'getFileRef')) {
                 $filerefs[] = $file_object->getFileRef();
             }
         }
diff --git a/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php b/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php
index 0ff06032545..2ed1a23f0c8 100644
--- a/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php
+++ b/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php
@@ -2,6 +2,7 @@
 
 namespace JsonApi\Routes\Files;
 
+use FileRef;
 use Psr\Http\Message\ServerRequestInterface as Request;
 use Psr\Http\Message\ResponseInterface as Response;
 use JsonApi\Errors\AuthorizationFailedException;
@@ -28,8 +29,14 @@ class SubfilerefsIndex extends JsonApiController
             throw new AuthorizationFailedException();
         }
 
-        $fileRefs = $folder->file_refs->getArrayCopy();
-        list($offset, $limit) = $this->getOffsetAndLimit();
+        $fileRefs = array_map(
+            function (\FileType $file): FileRef {
+                return $file->getFileRef();
+            },
+            $folder->getFiles()
+        );
+
+        [$offset, $limit] = $this->getOffsetAndLimit();
 
         return $this->getPaginatedContentResponse(
             array_slice($fileRefs, $offset, $limit),
diff --git a/lib/classes/JsonApi/Schemas/File.php b/lib/classes/JsonApi/Schemas/File.php
index 8eb80469da2..df0263a5eaa 100644
--- a/lib/classes/JsonApi/Schemas/File.php
+++ b/lib/classes/JsonApi/Schemas/File.php
@@ -29,7 +29,7 @@ class File extends SchemaProvider
             'chdate' => date('c', $resource['chdate']),
         ];
 
-        if ($resource['metadata']['url']) {
+        if (!empty($resource['metadata']['url'])) {
             if (FilesAuthority::canUpdateFile($this->currentUser, $resource)) {
                 $attributes['url'] = $resource['metadata']['url'];
             }
diff --git a/lib/classes/JsonApi/Schemas/Folder.php b/lib/classes/JsonApi/Schemas/Folder.php
index 2c61cae4ba2..4cb277ea3b7 100644
--- a/lib/classes/JsonApi/Schemas/Folder.php
+++ b/lib/classes/JsonApi/Schemas/Folder.php
@@ -169,14 +169,24 @@ class Folder extends SchemaProvider
         return $relationships;
     }
 
+    /**
+     * @param \FolderType $resource
+     */
     private function getFilesRelationship(array $relationships, $resource)
     {
+        $fileRefs = array_map(
+            function (\FileType $file): \FileRef {
+                return $file->getFileRef();
+            },
+            $resource->getFiles()
+        );
+
         $relationships[self::REL_FILE_REFS] = [
             self::RELATIONSHIP_LINKS => [
                 Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_FILE_REFS),
             ],
             self::RELATIONSHIP_META => [
-                'count' => count($resource->file_refs)
+                'count' => count($fileRefs),
             ],
         ];
 
diff --git a/lib/filesystem/HomeworkFolder.php b/lib/filesystem/HomeworkFolder.php
index 70447fb6cf6..fb93ef8147c 100644
--- a/lib/filesystem/HomeworkFolder.php
+++ b/lib/filesystem/HomeworkFolder.php
@@ -82,10 +82,6 @@ class HomeworkFolder extends PermissionEnabledFolder
         $template = $GLOBALS['template_factory']->open('filesystem/homework_folder/description.php');
         $template->folder     = $this;
         $template->folderdata = $this->folderdata;
-        if (!Seminar_Perm::get()->have_studip_perm('tutor', $this->range_id)) {
-            $files = new SimpleCollection($this->getFiles());
-            $template->own_files = $files->findBy('user_id', $GLOBALS['user']->id)->orderBy('name');
-        }
 
         return $template;
     }
@@ -100,6 +96,28 @@ class HomeworkFolder extends PermissionEnabledFolder
         return '';
     }
 
+    /**
+     * @param string $user_id
+     * @return bool
+     */
+    public function isReadable($user_id = null)
+    {
+        return StandardFolder::isReadable($user_id);
+    }
+
+    /**
+     * Determines if a user may see the file.
+     * @param FileRef|string $fileref_or_id
+     * @param string $user_id
+     * @return bool
+     */
+    public function isFileVisible($fileref_or_id, $user_id)
+    {
+        $fileref = FileRef::toObject($fileref_or_id);
+
+        return $fileref->user_id === $user_id || parent::isReadable($user_id);
+    }
+
     /**
      * @param FileRef|string $fileref_or_id
      * @param string $user_id
diff --git a/lib/filesystem/PermissionEnabledFolder.php b/lib/filesystem/PermissionEnabledFolder.php
index d41ebe39e5d..c286c5305af 100644
--- a/lib/filesystem/PermissionEnabledFolder.php
+++ b/lib/filesystem/PermissionEnabledFolder.php
@@ -117,6 +117,27 @@ class PermissionEnabledFolder extends StandardFolder
         return '';
     }
 
+    /**
+     * @return FileType[]
+     */
+    public function getFiles()
+    {
+        return array_filter(parent::getFiles(), function($file) {
+            return $this->isFileVisible($file->getFileRef(), $GLOBALS['user']->id);
+        });
+    }
+
+    /**
+     * Determines if a user may see the file.
+     * @param FileRef|string $fileref_or_id
+     * @param string $user_id
+     * @return bool
+     */
+    public function isFileVisible($fileref_or_id, $user_id)
+    {
+        return $this->isReadable($user_id);
+    }
+
     /**
      * @param $fileref_or_id
      * @param $user_id
@@ -127,7 +148,7 @@ class PermissionEnabledFolder extends StandardFolder
         $fileref = FileRef::toObject($fileref_or_id);
 
         if (is_object($fileref)) {
-            if ($this->isVisible($user_id) && $this->isReadable($user_id)) {
+            if ($this->isVisible($user_id) && $this->isFileVisible($fileref, $user_id)) {
                 return $fileref->terms_of_use->isDownloadable($this->range_id, $this->range_type, true, $user_id);
             }
         }
diff --git a/lib/filesystem/TimedFolder.php b/lib/filesystem/TimedFolder.php
index 442c084aa1b..33fec5aeaef 100644
--- a/lib/filesystem/TimedFolder.php
+++ b/lib/filesystem/TimedFolder.php
@@ -81,7 +81,7 @@ class TimedFolder extends PermissionEnabledFolder
                 ($this->end_time == 0 || $this->end_time >= $now)
                 ||
                 $GLOBALS['perm']->have_studip_perm($this->must_have_perm, $this->range_id, $user_id)) &&
-            parent::isReadable($user_id);
+            StandardFolder::isReadable($user_id);
     }
 
     public function isWritable($user_id = null)
@@ -95,6 +95,19 @@ class TimedFolder extends PermissionEnabledFolder
             parent::isWritable($user_id);
     }
 
+    /**
+     * Determines if a user may see the file.
+     * @param FileRef|string $fileref_or_id
+     * @param string $user_id
+     * @return bool
+     */
+    public function isFileVisible($fileref_or_id, $user_id)
+    {
+        $fileref = FileRef::toObject($fileref_or_id);
+
+        return $fileref->user_id === $user_id || parent::isReadable($user_id);
+    }
+
     /**
      * This function returns the suitable Icon for this folder type (TimedFolder)
      *
@@ -143,12 +156,6 @@ class TimedFolder extends PermissionEnabledFolder
         $template->folder     = $this;
         $template->folderdata = $this->folderdata;
 
-        if (!Seminar_Perm::get()->have_studip_perm('tutor', $this->range_id) &&
-                $this->isWritable($GLOBALS['user']->id) && !$this->isReadable($GLOBALS['user']->id)) {
-            $files = new SimpleCollection($this->getFiles());
-            $template->own_files = $files->findBy('user_id', $GLOBALS['user']->id)->orderBy('name');
-        }
-
         return $template;
     }
 
diff --git a/templates/filesystem/homework_folder/description.php b/templates/filesystem/homework_folder/description.php
index b3bc7f1b389..c47d6b0c996 100644
--- a/templates/filesystem/homework_folder/description.php
+++ b/templates/filesystem/homework_folder/description.php
@@ -1,14 +1,7 @@
 <div style="font-style: italic">
     <?=_("Dieser Ordner ist ein Hausaufgabenordner. Es können nur Dateien eingestellt werden.")?>
 </div>
-<? if (!empty($own_files) && count($own_files) > 0) : ?>
-<?= _("Sie selbst haben folgende Dateien in diesen Ordner eingestellt:") ?>
-    <ul>
-        <? foreach ($own_files as $own_file) :?>
-            <li><?=htmlReady($own_file->name)?> - <?=strftime('%x %X', $own_file->chdate)?></li>
-        <? endforeach ?>
-    </ul>
-<? endif ?>
+
 <? if ($folderdata['description']) : ?>
 <hr>
     <div>
diff --git a/templates/filesystem/timed_folder/description.php b/templates/filesystem/timed_folder/description.php
index ae5bd9e744c..396a2864ad5 100644
--- a/templates/filesystem/timed_folder/description.php
+++ b/templates/filesystem/timed_folder/description.php
@@ -36,17 +36,6 @@
 <? endif ?>
 </div>
 
-<? if (!empty($own_files) && count($own_files) > 0) : ?>
-    <div>
-        <?= _('Sie selbst haben folgende Dateien in diesen Ordner eingestellt:') ?>
-        <ul>
-            <? foreach ($own_files as $own_file) : ?>
-                <li><?= htmlReady($own_file->name) ?> - <?= strftime('%x %X', $own_file->chdate) ?></li>
-            <? endforeach ?>
-        </ul>
-    </div>
-<? endif ?>
-
 <? if ($folderdata['description']) : ?>
 <hr>
     <div>
-- 
GitLab