aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2025-02-28 17:42:55 +0100
committerRobin Appelman <robin@icewind.nl>2025-06-06 17:12:33 +0200
commitb313aaea7ef96b3ae909cdc6b87af9a354e5db4b (patch)
tree1f83653525a4ab582327301900b70b393a82e143
parent92c97c3447437690389dd7bf94ccba429abbb03e (diff)
downloadnextcloud-server-home-folder-readonly.tar.gz
nextcloud-server-home-folder-readonly.zip
feat: mark homefolder as overwritten when an external storage mounted at / existshome-folder-readonly
Signed-off-by: Robin Appelman <robin@icewind.nl>
-rw-r--r--apps/files_external/appinfo/info.xml2
-rw-r--r--apps/files_external/composer/composer/autoload_classmap.php1
-rw-r--r--apps/files_external/composer/composer/autoload_static.php1
-rw-r--r--apps/files_external/lib/Migration/Version1025Date20250228162604.php40
-rw-r--r--apps/files_external/lib/Service/DBConfigService.php30
-rw-r--r--apps/files_external/lib/Service/StoragesService.php6
-rw-r--r--apps/files_external/lib/Service/UserGlobalStoragesService.php4
-rw-r--r--apps/files_external/lib/Service/UserStoragesService.php4
-rw-r--r--apps/files_external/tests/Service/GlobalStoragesServiceTest.php2
-rw-r--r--apps/files_external/tests/Service/StoragesServiceTestCase.php6
-rw-r--r--apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php1
-rw-r--r--apps/files_external/tests/Service/UserStoragesServiceTest.php4
12 files changed, 88 insertions, 13 deletions
diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml
index e746f052619..8c30054b73b 100644
--- a/apps/files_external/appinfo/info.xml
+++ b/apps/files_external/appinfo/info.xml
@@ -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>
diff --git a/apps/files_external/composer/composer/autoload_classmap.php b/apps/files_external/composer/composer/autoload_classmap.php
index 90f41f0e920..7492884d9e1 100644
--- a/apps/files_external/composer/composer/autoload_classmap.php
+++ b/apps/files_external/composer/composer/autoload_classmap.php
@@ -108,6 +108,7 @@ return array(
'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',
diff --git a/apps/files_external/composer/composer/autoload_static.php b/apps/files_external/composer/composer/autoload_static.php
index 7b5eb5feabe..da24e8bc60a 100644
--- a/apps/files_external/composer/composer/autoload_static.php
+++ b/apps/files_external/composer/composer/autoload_static.php
@@ -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',
diff --git a/apps/files_external/lib/Migration/Version1025Date20250228162604.php b/apps/files_external/lib/Migration/Version1025Date20250228162604.php
new file mode 100644
index 00000000000..71af435f93e
--- /dev/null
+++ b/apps/files_external/lib/Migration/Version1025Date20250228162604.php
@@ -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);
+ }
+ }
+}
diff --git a/apps/files_external/lib/Service/DBConfigService.php b/apps/files_external/lib/Service/DBConfigService.php
index 3820f6b0d96..9e72eb62971 100644
--- a/apps/files_external/lib/Service/DBConfigService.php
+++ b/apps/files_external/lib/Service/DBConfigService.php
@@ -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;
@@ -63,16 +64,16 @@ class DBConfigService {
->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);
@@ -93,8 +94,8 @@ class DBConfigService {
->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();
@@ -226,7 +227,7 @@ class DBConfigService {
'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();
@@ -497,4 +498,19 @@ class DBConfigService {
return $value;
}
}
+
+ /**
+ * Check if any mountpoint is configured that overwrite the home folder
+ *
+ * @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();
+ }
}
diff --git a/apps/files_external/lib/Service/StoragesService.php b/apps/files_external/lib/Service/StoragesService.php
index 73642d85f88..29fa3902ae5 100644
--- a/apps/files_external/lib/Service/StoragesService.php
+++ b/apps/files_external/lib/Service/StoragesService.php
@@ -19,6 +19,7 @@ use OCP\EventDispatcher\IEventDispatcher;
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;
@@ -39,6 +40,7 @@ abstract class StoragesService {
protected DBConfigService $dbConfig,
protected IUserMountCache $userMountCache,
protected IEventDispatcher $eventDispatcher,
+ protected IAppConfig $appConfig,
) {
}
@@ -424,6 +426,10 @@ abstract class StoragesService {
}
}
+ if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
+ $this->appConfig->setValueBool('files', 'homeFolderOverwritten', true);
+ }
+
return $this->getStorage($id);
}
diff --git a/apps/files_external/lib/Service/UserGlobalStoragesService.php b/apps/files_external/lib/Service/UserGlobalStoragesService.php
index 01bc91ef3ff..f5feb1b0a98 100644
--- a/apps/files_external/lib/Service/UserGlobalStoragesService.php
+++ b/apps/files_external/lib/Service/UserGlobalStoragesService.php
@@ -9,6 +9,7 @@ namespace OCA\Files_External\Service;
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;
@@ -35,8 +36,9 @@ class UserGlobalStoragesService extends GlobalStoragesService {
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;
}
diff --git a/apps/files_external/lib/Service/UserStoragesService.php b/apps/files_external/lib/Service/UserStoragesService.php
index defa97451cd..a0ffa2fdbb1 100644
--- a/apps/files_external/lib/Service/UserStoragesService.php
+++ b/apps/files_external/lib/Service/UserStoragesService.php
@@ -12,6 +12,7 @@ use OCA\Files_External\MountConfig;
use OCA\Files_External\NotFoundException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
+use OCP\IAppConfig;
use OCP\IUserSession;
/**
@@ -36,9 +37,10 @@ class UserStoragesService extends StoragesService {
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() {
diff --git a/apps/files_external/tests/Service/GlobalStoragesServiceTest.php b/apps/files_external/tests/Service/GlobalStoragesServiceTest.php
index 47be54a02d4..1ca75bb2332 100644
--- a/apps/files_external/tests/Service/GlobalStoragesServiceTest.php
+++ b/apps/files_external/tests/Service/GlobalStoragesServiceTest.php
@@ -19,7 +19,7 @@ use OCA\Files_External\Service\GlobalStoragesService;
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 {
diff --git a/apps/files_external/tests/Service/StoragesServiceTestCase.php b/apps/files_external/tests/Service/StoragesServiceTestCase.php
index a5cffd45ec2..8c916b8a456 100644
--- a/apps/files_external/tests/Service/StoragesServiceTestCase.php
+++ b/apps/files_external/tests/Service/StoragesServiceTestCase.php
@@ -28,6 +28,7 @@ use OCP\Files\Cache\ICache;
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;
@@ -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;
protected function setUp(): void {
parent::setUp();
@@ -77,6 +82,7 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
$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);
diff --git a/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php b/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php
index 1ec4e56bd9e..92c99519ff4 100644
--- a/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php
+++ b/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php
@@ -74,6 +74,7 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
$this->groupManager,
$this->mountCache,
$this->eventDispatcher,
+ $this->appConfig,
);
}
diff --git a/apps/files_external/tests/Service/UserStoragesServiceTest.php b/apps/files_external/tests/Service/UserStoragesServiceTest.php
index 53d7f5960e8..39357f997aa 100644
--- a/apps/files_external/tests/Service/UserStoragesServiceTest.php
+++ b/apps/files_external/tests/Service/UserStoragesServiceTest.php
@@ -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);
@@ -47,7 +47,7 @@ class UserStoragesServiceTest extends StoragesServiceTestCase {
->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() {