-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Closed as not planned
Closed as not planned
Copy link
Labels
0. Needs triagePending check for reproducibility or if it fits our roadmapPending check for reproducibility or if it fits our roadmap32-feedbackbugfeature: davfeature: sharinggood first issueSmall tasks with clear documentation about how and in which place you need to fix things in.Small tasks with clear documentation about how and in which place you need to fix things in.
Description
This seems like a bug that i noticed when trying to check for the permissions using @nextcloud/files where it turned out my file action did not hide on read only shares.
Steps to reproduce
- as userA: Share a single file as view only (permission: 1) to userB
- as userB: Check the webdav response and see
<oc:permissions>SGDNV</oc:permissions>indicating that the file can be updated
Additional context
- This does not happen with folder shares, there both the root mount and files within have correct webdav permissions exposed
- I already spend some time stepping through code
- Permissions in the FileInfo in are already wrong with 11 (unsure where that is originating from, but my guess is somewhere in
server/lib/public/Files/DavUtil.php
Line 36 in dae7c15
$permissions = $info->getPermissions(); )server/lib/private/Files/View.php
Lines 1482 to 1650 in 01db539
public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Files\FileInfo $directoryInfo = null) { $this->assertPathLength($directory); if (!Filesystem::isValidPath($directory)) { return []; } $path = $this->getAbsolutePath($directory); $path = Filesystem::normalizePath($path); $mount = $this->getMount($directory); $storage = $mount->getStorage(); $internalPath = $mount->getInternalPath($path); if (!$storage) { return []; } $cache = $storage->getCache($internalPath); $user = \OC_User::getUser(); if (!$directoryInfo) { $data = $this->getCacheEntry($storage, $internalPath, $directory); if (!$data instanceof ICacheEntry || !isset($data['fileid'])) { return []; } } else { $data = $directoryInfo; } if (!($data->getPermissions() & Constants::PERMISSION_READ)) { return []; } $folderId = $data->getId(); $contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter $sharingDisabled = \OCP\Util::isSharingDisabledForUser(); $fileNames = array_map(function (ICacheEntry $content) { return $content->getName(); }, $contents); /** * @var \OC\Files\FileInfo[] $fileInfos */ $fileInfos = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) { if ($sharingDisabled) { $content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; } $ownerId = $storage->getOwner($content['path']); if ($ownerId !== false) { $owner = $this->getUserObjectForOwner($ownerId); } else { $owner = null; } return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner); }, $contents); $files = array_combine($fileNames, $fileInfos); //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders $mounts = Filesystem::getMountManager()->findIn($path); // make sure nested mounts are sorted after their parent mounts // otherwise doesn't propagate the etag across storage boundaries correctly usort($mounts, function (IMountPoint $a, IMountPoint $b) { return $a->getMountPoint() <=> $b->getMountPoint(); }); $dirLength = strlen($path); foreach ($mounts as $mount) { $mountPoint = $mount->getMountPoint(); $subStorage = $mount->getStorage(); if ($subStorage) { $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); if (!$rootEntry) { $subScanner = $subStorage->getScanner(); try { $subScanner->scanFile(''); } catch (\OCP\Files\StorageNotAvailableException $e) { continue; } catch (\OCP\Files\StorageInvalidException $e) { continue; } catch (\Exception $e) { // sometimes when the storage is not available it can be any exception $this->logger->error('Exception while scanning storage "' . $subStorage->getId() . '"', [ 'exception' => $e, 'app' => 'core', ]); continue; } $rootEntry = $subCache->get(''); } if ($rootEntry && ($rootEntry->getPermissions() & Constants::PERMISSION_READ)) { $relativePath = trim(substr($mountPoint, $dirLength), '/'); if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder $entryName = substr($relativePath, 0, $pos); // Create parent folders if the mountpoint is inside a subfolder that doesn't exist yet if (!isset($files[$entryName])) { try { [$storage, ] = $this->resolvePath($path . '/' . $entryName); // make sure we can create the mountpoint folder, even if the user has a quota of 0 if ($storage->instanceOfStorage(Quota::class)) { $storage->enableQuota(false); } if ($this->mkdir($path . '/' . $entryName) !== false) { $info = $this->getFileInfo($path . '/' . $entryName); if ($info !== false) { $files[$entryName] = $info; } } if ($storage->instanceOfStorage(Quota::class)) { $storage->enableQuota(true); } } catch (\Exception $e) { // Creating the parent folder might not be possible, for example due to a lack of permissions. $this->logger->debug('Failed to create non-existent parent', ['exception' => $e, 'path' => $path . '/' . $entryName]); } } if (isset($files[$entryName])) { $files[$entryName]->addSubEntry($rootEntry, $mountPoint); } } else { //mountpoint in this folder, add an entry for it $rootEntry['name'] = $relativePath; $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; $permissions = $rootEntry['permissions']; // do not allow renaming/deleting the mount point if they are not shared files/folders // for shared files/folders we use the permissions given by the owner if ($mount instanceof MoveableMount) { $rootEntry['permissions'] = $permissions | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; } else { $rootEntry['permissions'] = $permissions & (\OCP\Constants::PERMISSION_ALL - (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)); } $rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/ // if sharing was disabled for the user we remove the share permissions if ($sharingDisabled) { $rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; } $ownerId = $subStorage->getOwner(''); if ($ownerId !== false) { $owner = $this->getUserObjectForOwner($ownerId); } else { $owner = null; } $files[$rootEntry->getName()] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner); } } } } if ($mimetype_filter) { $files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) { if (strpos($mimetype_filter, '/')) { return $file->getMimetype() === $mimetype_filter; } else { return $file->getMimePart() === $mimetype_filter; } }); } return array_values($files); }
- Permissions in the FileInfo in
Metadata
Metadata
Assignees
Labels
0. Needs triagePending check for reproducibility or if it fits our roadmapPending check for reproducibility or if it fits our roadmap32-feedbackbugfeature: davfeature: sharinggood first issueSmall tasks with clear documentation about how and in which place you need to fix things in.Small tasks with clear documentation about how and in which place you need to fix things in.