Skip to content

add appconfig to disable fixed userfolder permissions optimization #51145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/files_external/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This application enables administrators to configure connections to external sto

External storage can be configured using the GUI or at the command line. This second option provides the administration with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation.
</description>
<version>1.24.0</version>
<version>1.25.0</version>
<licence>agpl</licence>
<author>Robin Appelman</author>
<author>Michael Gapczynski</author>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
'OCA\\Files_External\\Migration\\Version1011Date20200630192246' => $baseDir . '/../lib/Migration/Version1011Date20200630192246.php',
'OCA\\Files_External\\Migration\\Version1015Date20211104103506' => $baseDir . '/../lib/Migration/Version1015Date20211104103506.php',
'OCA\\Files_External\\Migration\\Version1016Date20220324154536' => $baseDir . '/../lib/Migration/Version1016Date20220324154536.php',
'OCA\\Files_External\\Migration\\Version1025Date20250228162604' => $baseDir . '/../lib/Migration/Version1025Date20250228162604.php',
'OCA\\Files_External\\Migration\\Version22000Date20210216084416' => $baseDir . '/../lib/Migration/Version22000Date20210216084416.php',
'OCA\\Files_External\\MountConfig' => $baseDir . '/../lib/MountConfig.php',
'OCA\\Files_External\\NotFoundException' => $baseDir . '/../lib/NotFoundException.php',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class ComposerStaticInitFiles_External
'OCA\\Files_External\\Migration\\Version1011Date20200630192246' => __DIR__ . '/..' . '/../lib/Migration/Version1011Date20200630192246.php',
'OCA\\Files_External\\Migration\\Version1015Date20211104103506' => __DIR__ . '/..' . '/../lib/Migration/Version1015Date20211104103506.php',
'OCA\\Files_External\\Migration\\Version1016Date20220324154536' => __DIR__ . '/..' . '/../lib/Migration/Version1016Date20220324154536.php',
'OCA\\Files_External\\Migration\\Version1025Date20250228162604' => __DIR__ . '/..' . '/../lib/Migration/Version1025Date20250228162604.php',
'OCA\\Files_External\\Migration\\Version22000Date20210216084416' => __DIR__ . '/..' . '/../lib/Migration/Version22000Date20210216084416.php',
'OCA\\Files_External\\MountConfig' => __DIR__ . '/..' . '/../lib/MountConfig.php',
'OCA\\Files_External\\NotFoundException' => __DIR__ . '/..' . '/../lib/NotFoundException.php',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Files_External\Migration;

use Closure;
use OCA\Files_External\Service\DBConfigService;
use OCP\DB\ISchemaWrapper;
use OCP\IAppConfig;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

/**
* Check for any external storage overwriting the home folder
*/
class Version1025Date20250228162604 extends SimpleMigrationStep {
public function __construct(
private DBConfigService $dbConfig,
private IAppConfig $appConfig,
) {
}


/**
* @param IOutput $output
* @param Closure(): ISchemaWrapper $schemaClosure
* @param array $options
*/
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
$this->appConfig->setValueBool('files', 'homeFolderOverwritten', true);
}
}
}
30 changes: 23 additions & 7 deletions apps/files_external/lib/Service/DBConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/

namespace OCA\Files_External\Service;

use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
Expand Down Expand Up @@ -63,16 +64,16 @@
->where($builder->expr()->orX(
$builder->expr()->andX( // global mounts
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
$builder->expr()->isNull('a.value')
$builder->expr()->isNull('a.value'),
),
$builder->expr()->andX( // mounts for user
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId))
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
),
$builder->expr()->andX( // mounts for group
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY))
)
$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
),
));

return $this->getMountsFromQuery($query);
Expand All @@ -93,8 +94,8 @@
->leftJoin('a', 'external_applicable', 'b', $builder->expr()->eq('a.mount_id', 'b.mount_id'))
->where($builder->expr()->andX(
$builder->expr()->eq('b.type', $builder->createNamedParameter($applicableType, IQueryBuilder::PARAM_INT)),
$builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId))
)
$builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)),
),
)
->groupBy(['a.mount_id']);
$stmt = $query->executeQuery();
Expand Down Expand Up @@ -226,7 +227,7 @@
'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR),
'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR),
'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT),
'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)
'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT),
]);
$query->executeStatement();
return $query->getLastInsertId();
Expand Down Expand Up @@ -497,4 +498,19 @@
return $value;
}
}

/**
* Check if any mountpoint is configured that overwrite the home folder
*
* @return bool
Comment on lines +504 to +505
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*
* @return bool

*/
public function hasHomeFolderOverwriteMount(): bool {
$builder = $this->connection->getQueryBuilder();
$query = $builder->select('mount_id')
->from('external_mounts')
->where($builder->expr()->eq('mount_point', $builder->createNamedParameter('/')))
->setMaxResults(1);
$result = $query->executeQuery();
return (bool)$result->fetchColumn();

Check failure on line 514 in apps/files_external/lib/Service/DBConfigService.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

DeprecatedMethod

apps/files_external/lib/Service/DBConfigService.php:514:25: DeprecatedMethod: The method OCP\DB\IResult::fetchColumn has been marked as deprecated (see https://psalm.dev/001)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return (bool)$result->fetchColumn();
return (bool)$result->fetchOne();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even

Suggested change
return (bool)$result->fetchColumn();
return $result->rowCount() > 0;

}
}
6 changes: 6 additions & 0 deletions apps/files_external/lib/Service/StoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use OCP\Files\Config\IUserMountCache;
use OCP\Files\Events\InvalidateMountCacheEvent;
use OCP\Files\StorageNotAvailableException;
use OCP\IAppConfig;
use OCP\Server;
use OCP\Util;
use Psr\Log\LoggerInterface;
Expand All @@ -39,6 +40,7 @@ public function __construct(
protected DBConfigService $dbConfig,
protected IUserMountCache $userMountCache,
protected IEventDispatcher $eventDispatcher,
protected IAppConfig $appConfig,
) {
}

Expand Down Expand Up @@ -424,6 +426,10 @@ public function updateStorage(StorageConfig $updatedStorage) {
}
}

if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
$this->appConfig->setValueBool('files', 'homeFolderOverwritten', true);
}
Comment on lines +429 to +431
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is it ever set to false?
Shouldn’t it be:

Suggested change
if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
$this->appConfig->setValueBool('files', 'homeFolderOverwritten', true);
}
$this->appConfig->setValueBool('files', 'homeFolderOverwritten', $this->dbConfig->hasHomeFolderOverwriteMount()));


return $this->getStorage($id);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use OCA\Files_External\Lib\StorageConfig;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
use OCP\IAppConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
Expand All @@ -35,8 +36,9 @@ public function __construct(
protected IGroupManager $groupManager,
IUserMountCache $userMountCache,
IEventDispatcher $eventDispatcher,
IAppConfig $appConfig,
) {
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher);
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
$this->userSession = $userSession;
}

Expand Down
4 changes: 3 additions & 1 deletion apps/files_external/lib/Service/UserStoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OCA\Files_External\NotFoundException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
use OCP\IAppConfig;
use OCP\IUserSession;

/**
Expand All @@ -36,9 +37,10 @@ public function __construct(
IUserSession $userSession,
IUserMountCache $userMountCache,
IEventDispatcher $eventDispatcher,
IAppConfig $appConfig,
) {
$this->userSession = $userSession;
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher);
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
}

protected function readDBConfig() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class GlobalStoragesServiceTest extends StoragesServiceTestCase {
protected function setUp(): void {
parent::setUp();
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher);
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher, $this->appConfig);
}

protected function tearDown(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use OCP\Files\Config\IUserMountCache;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Storage\IStorage;
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUser;
Expand Down Expand Up @@ -63,6 +64,10 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
protected static array $hookCalls;
protected IUserMountCache&MockObject $mountCache;
protected IEventDispatcher&MockObject $eventDispatcher;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IAppConfig
*/
protected IAppConfig $appConfig;
Comment on lines +67 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IAppConfig
*/
protected IAppConfig $appConfig;
protected IAppConfig&MockObject $appConfig;


protected function setUp(): void {
parent::setUp();
Expand All @@ -77,6 +82,7 @@ protected function setUp(): void {

$this->mountCache = $this->createMock(IUserMountCache::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->appConfig = $this->createMock(IAppConfig::class);

// prepare BackendService mock
$this->backendService = $this->createMock(BackendService::class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ protected function setUp(): void {
$this->groupManager,
$this->mountCache,
$this->eventDispatcher,
$this->appConfig,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class UserStoragesServiceTest extends StoragesServiceTestCase {
protected function setUp(): void {
parent::setUp();

$this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher);
$this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher, $this->appConfig);

$this->userId = $this->getUniqueID('user_');
$this->createUser($this->userId, $this->userId);
Expand All @@ -47,7 +47,7 @@ protected function setUp(): void {
->method('getUser')
->willReturn($this->user);

$this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache, $this->eventDispatcher);
$this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache, $this->eventDispatcher, $this->appConfig);
}

private function makeTestStorageData() {
Expand Down
20 changes: 12 additions & 8 deletions lib/private/Files/Node/LazyUserFolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,20 @@ class LazyUserFolder extends LazyFolder {
private string $path;
private IMountManager $mountManager;

public function __construct(IRootFolder $rootFolder, IUser $user, IMountManager $mountManager) {
public function __construct(IRootFolder $rootFolder, IUser $user, IMountManager $mountManager, bool $useDefaultPermissions = true) {
$this->user = $user;
$this->mountManager = $mountManager;
$this->path = '/' . $user->getUID() . '/files';
$data = [
'path' => $this->path,
// Sharing user root folder is not allowed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be before line 37, it comments the permission setting.

'type' => FileInfo::TYPE_FOLDER,
'mimetype' => FileInfo::MIMETYPE_FOLDER,
];
if ($useDefaultPermissions) {
$data['permissions'] = Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE;
}

parent::__construct($rootFolder, function () use ($user): Folder {
try {
$node = $this->getRootFolder()->get($this->path);
Expand All @@ -44,13 +54,7 @@ public function __construct(IRootFolder $rootFolder, IUser $user, IMountManager
}
return $this->getRootFolder()->newFolder($this->path);
}
}, [
'path' => $this->path,
// Sharing user root folder is not allowed
'permissions' => Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE,
'type' => FileInfo::TYPE_FOLDER,
'mimetype' => FileInfo::MIMETYPE_FOLDER,
]);
}, $data);
}

public function getMountPoint() {
Expand Down
6 changes: 5 additions & 1 deletion lib/private/Files/Node/Root.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use OCP\Files\Node as INode;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IAppConfig;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IUser;
Expand Down Expand Up @@ -60,6 +61,7 @@ class Root extends Folder implements IRootFolder {
private IUserManager $userManager;
private IEventDispatcher $eventDispatcher;
private ICache $pathByIdCache;
private bool $homeFolderOverwritten = false;

/**
* @param Manager $manager
Expand All @@ -75,6 +77,7 @@ public function __construct(
IUserManager $userManager,
IEventDispatcher $eventDispatcher,
ICacheFactory $cacheFactory,
IAppConfig $appConfig,
) {
parent::__construct($this, $view, '');
$this->mountManager = $manager;
Expand All @@ -88,6 +91,7 @@ public function __construct(
$this->userFolderCache = new CappedMemoryCache();
});
$this->pathByIdCache = $cacheFactory->createLocal('path-by-id');
$this->homeFolderOverwritten = $appConfig->getValueBool('files', 'homeFolderOverwritten');
}

/**
Expand Down Expand Up @@ -367,7 +371,7 @@ public function getUserFolder($userId) {
$folder = $this->newFolder('/' . $userId . '/files');
}
} else {
$folder = new LazyUserFolder($this, $userObject, $this->mountManager);
$folder = new LazyUserFolder($this, $userObject, $this->mountManager, !$this->homeFolderOverwritten);
}

$this->userFolderCache->set($userId, $folder);
Expand Down
1 change: 1 addition & 0 deletions lib/private/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ public function __construct($webRoot, \OC\Config $config) {
$this->get(IUserManager::class),
$this->get(IEventDispatcher::class),
$this->get(ICacheFactory::class),
$this->get(IAppConfig::class),
);

$previewConnector = new \OC\Preview\WatcherConnector(
Expand Down
Loading
Loading