Skip to content

Commit 0ba0756

Browse files
committed
feat(files): Mark homefolder as overwritten when an external storage mounted at / exists
Signed-off-by: Robin Appelman <robin@icewind.nl> Signed-off-by: Louis Chemineau <louis@chmn.me>
1 parent 99120d4 commit 0ba0756

11 files changed

+98
-27
lines changed

apps/files_external/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
'OCA\\Files_External\\Migration\\Version1011Date20200630192246' => $baseDir . '/../lib/Migration/Version1011Date20200630192246.php',
108108
'OCA\\Files_External\\Migration\\Version1015Date20211104103506' => $baseDir . '/../lib/Migration/Version1015Date20211104103506.php',
109109
'OCA\\Files_External\\Migration\\Version1016Date20220324154536' => $baseDir . '/../lib/Migration/Version1016Date20220324154536.php',
110+
'OCA\\Files_External\\Migration\\Version1025Date20250228162604' => $baseDir . '/../lib/Migration/Version1025Date20250228162604.php',
110111
'OCA\\Files_External\\Migration\\Version22000Date20210216084416' => $baseDir . '/../lib/Migration/Version22000Date20210216084416.php',
111112
'OCA\\Files_External\\MountConfig' => $baseDir . '/../lib/MountConfig.php',
112113
'OCA\\Files_External\\NotFoundException' => $baseDir . '/../lib/NotFoundException.php',

apps/files_external/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class ComposerStaticInitFiles_External
122122
'OCA\\Files_External\\Migration\\Version1011Date20200630192246' => __DIR__ . '/..' . '/../lib/Migration/Version1011Date20200630192246.php',
123123
'OCA\\Files_External\\Migration\\Version1015Date20211104103506' => __DIR__ . '/..' . '/../lib/Migration/Version1015Date20211104103506.php',
124124
'OCA\\Files_External\\Migration\\Version1016Date20220324154536' => __DIR__ . '/..' . '/../lib/Migration/Version1016Date20220324154536.php',
125+
'OCA\\Files_External\\Migration\\Version1025Date20250228162604' => __DIR__ . '/..' . '/../lib/Migration/Version1025Date20250228162604.php',
125126
'OCA\\Files_External\\Migration\\Version22000Date20210216084416' => __DIR__ . '/..' . '/../lib/Migration/Version22000Date20210216084416.php',
126127
'OCA\\Files_External\\MountConfig' => __DIR__ . '/..' . '/../lib/MountConfig.php',
127128
'OCA\\Files_External\\NotFoundException' => __DIR__ . '/..' . '/../lib/NotFoundException.php',
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Files_External\Migration;
11+
12+
use Closure;
13+
use OCA\Files_External\Service\GlobalStoragesService;
14+
use OCP\DB\ISchemaWrapper;
15+
use OCP\IAppConfig;
16+
use OCP\Migration\IOutput;
17+
use OCP\Migration\SimpleMigrationStep;
18+
19+
/**
20+
* Check for any external storage overwriting the home folder
21+
*/
22+
class Version1025Date20250228162604 extends SimpleMigrationStep {
23+
public function __construct(
24+
private GlobalStoragesService $globalStoragesServices,
25+
private IAppConfig $appConfig,
26+
) {
27+
}
28+
29+
/**
30+
* @param Closure(): ISchemaWrapper $schemaClosure
31+
*/
32+
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
33+
$this->globalStoragesServices->updateOverwriteHomeFolders();
34+
}
35+
}

apps/files_external/lib/Service/DBConfigService.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
66
* SPDX-License-Identifier: AGPL-3.0-only
77
*/
8+
89
namespace OCA\Files_External\Service;
910

1011
use OCP\DB\Exception;
@@ -64,16 +65,16 @@ public function getMountsForUser($userId, $groupIds) {
6465
->where($builder->expr()->orX(
6566
$builder->expr()->andX( // global mounts
6667
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
67-
$builder->expr()->isNull('a.value')
68+
$builder->expr()->isNull('a.value'),
6869
),
6970
$builder->expr()->andX( // mounts for user
7071
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
71-
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId))
72+
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
7273
),
7374
$builder->expr()->andX( // mounts for group
7475
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
75-
$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY))
76-
)
76+
$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
77+
),
7778
));
7879

7980
return $this->getMountsFromQuery($query);
@@ -94,8 +95,8 @@ protected function modifyMountsOnDelete(string $applicableId, int $applicableTyp
9495
->leftJoin('a', 'external_applicable', 'b', $builder->expr()->eq('a.mount_id', 'b.mount_id'))
9596
->where($builder->expr()->andX(
9697
$builder->expr()->eq('b.type', $builder->createNamedParameter($applicableType, IQueryBuilder::PARAM_INT)),
97-
$builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId))
98-
)
98+
$builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)),
99+
),
99100
)
100101
->groupBy(['a.mount_id']);
101102
$stmt = $query->executeQuery();
@@ -227,7 +228,7 @@ public function addMount($mountPoint, $storageBackend, $authBackend, $priority,
227228
'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR),
228229
'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR),
229230
'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT),
230-
'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)
231+
'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT),
231232
]);
232233
$query->executeStatement();
233234
return $query->getLastInsertId();
@@ -507,4 +508,17 @@ private function decryptValue($value) {
507508
return $value;
508509
}
509510
}
511+
512+
/**
513+
* Check if any mountpoint is configured that overwrite the home folder
514+
*/
515+
public function hasHomeFolderOverwriteMount(): bool {
516+
$builder = $this->connection->getQueryBuilder();
517+
$query = $builder->select('mount_id')
518+
->from('external_mounts')
519+
->where($builder->expr()->eq('mount_point', $builder->createNamedParameter('/')))
520+
->setMaxResults(1);
521+
$result = $query->executeQuery();
522+
return $result->rowCount() > 0;
523+
}
510524
}

apps/files_external/lib/Service/StoragesService.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
use OC\Files\Cache\Storage;
1111
use OC\Files\Filesystem;
12+
use OCA\Files\AppInfo\Application as FilesApplication;
13+
use OCA\Files\ConfigLexicon;
14+
use OCA\Files_External\AppInfo\Application;
1215
use OCA\Files_External\Lib\Auth\AuthMechanism;
1316
use OCA\Files_External\Lib\Auth\InvalidAuth;
1417
use OCA\Files_External\Lib\Backend\Backend;
@@ -20,6 +23,7 @@
2023
use OCP\Files\Config\IUserMountCache;
2124
use OCP\Files\Events\InvalidateMountCacheEvent;
2225
use OCP\Files\StorageNotAvailableException;
26+
use OCP\IAppConfig;
2327
use OCP\Server;
2428
use OCP\Util;
2529
use Psr\Log\LoggerInterface;
@@ -40,6 +44,7 @@ public function __construct(
4044
protected DBConfigService $dbConfig,
4145
protected IUserMountCache $userMountCache,
4246
protected IEventDispatcher $eventDispatcher,
47+
protected IAppConfig $appConfig,
4348
) {
4449
}
4550

@@ -242,6 +247,9 @@ public function addStorage(StorageConfig $newStorage) {
242247
$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
243248

244249
$newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS);
250+
251+
$this->updateOverwriteHomeFolders();
252+
245253
return $newStorage;
246254
}
247255

@@ -425,6 +433,8 @@ public function updateStorage(StorageConfig $updatedStorage) {
425433
}
426434
}
427435

436+
$this->updateOverwriteHomeFolders();
437+
428438
return $this->getStorage($id);
429439
}
430440

@@ -473,4 +483,20 @@ private function getStorageId(StorageConfig $storageConfig) {
473483
return -1;
474484
}
475485
}
486+
487+
public function updateOverwriteHomeFolders(): void {
488+
$appIdsList = $this->appConfig->getValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS);
489+
490+
if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
491+
if (!in_array(Application::APP_ID, $appIdsList)) {
492+
$appIdsList[] = Application::APP_ID;
493+
$this->appConfig->setValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS, $appIdsList);
494+
}
495+
} else {
496+
if (in_array(Application::APP_ID, $appIdsList)) {
497+
$appIdsList = array_values(array_filter($appIdsList, fn ($v) => $v !== Application::APP_ID));
498+
$this->appConfig->setValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS, $appIdsList);
499+
}
500+
}
501+
}
476502
}

apps/files_external/lib/Service/UserGlobalStoragesService.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use OCA\Files_External\Lib\StorageConfig;
1111
use OCP\EventDispatcher\IEventDispatcher;
1212
use OCP\Files\Config\IUserMountCache;
13+
use OCP\IAppConfig;
1314
use OCP\IGroupManager;
1415
use OCP\IUser;
1516
use OCP\IUserSession;
@@ -21,23 +22,16 @@
2122
class UserGlobalStoragesService extends GlobalStoragesService {
2223
use UserTrait;
2324

24-
/**
25-
* @param BackendService $backendService
26-
* @param DBConfigService $dbConfig
27-
* @param IUserSession $userSession
28-
* @param IGroupManager $groupManager
29-
* @param IUserMountCache $userMountCache
30-
* @param IEventDispatcher $eventDispatcher
31-
*/
3225
public function __construct(
3326
BackendService $backendService,
3427
DBConfigService $dbConfig,
3528
IUserSession $userSession,
3629
protected IGroupManager $groupManager,
3730
IUserMountCache $userMountCache,
3831
IEventDispatcher $eventDispatcher,
32+
IAppConfig $appConfig,
3933
) {
40-
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher);
34+
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
4135
$this->userSession = $userSession;
4236
}
4337

apps/files_external/lib/Service/UserStoragesService.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OCA\Files_External\NotFoundException;
1414
use OCP\EventDispatcher\IEventDispatcher;
1515
use OCP\Files\Config\IUserMountCache;
16+
use OCP\IAppConfig;
1617
use OCP\IUserSession;
1718

1819
/**
@@ -24,22 +25,17 @@ class UserStoragesService extends StoragesService {
2425

2526
/**
2627
* Create a user storages service
27-
*
28-
* @param BackendService $backendService
29-
* @param DBConfigService $dbConfig
30-
* @param IUserSession $userSession user session
31-
* @param IUserMountCache $userMountCache
32-
* @param IEventDispatcher $eventDispatcher
3328
*/
3429
public function __construct(
3530
BackendService $backendService,
3631
DBConfigService $dbConfig,
3732
IUserSession $userSession,
3833
IUserMountCache $userMountCache,
3934
IEventDispatcher $eventDispatcher,
35+
IAppConfig $appConfig,
4036
) {
4137
$this->userSession = $userSession;
42-
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher);
38+
parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
4339
}
4440

4541
protected function readDBConfig() {

apps/files_external/tests/Service/GlobalStoragesServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
class GlobalStoragesServiceTest extends StoragesServiceTestCase {
2020
protected function setUp(): void {
2121
parent::setUp();
22-
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher);
22+
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher, $this->appConfig);
2323
}
2424

2525
protected function tearDown(): void {

apps/files_external/tests/Service/StoragesServiceTestCase.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use OCP\Files\Config\IUserMountCache;
2929
use OCP\Files\Mount\IMountPoint;
3030
use OCP\Files\Storage\IStorage;
31+
use OCP\IAppConfig;
3132
use OCP\IConfig;
3233
use OCP\IDBConnection;
3334
use OCP\IUser;
@@ -57,12 +58,13 @@ public function clean() {
5758
*/
5859
abstract class StoragesServiceTestCase extends \Test\TestCase {
5960
protected StoragesService $service;
60-
protected BackendService $backendService;
61+
protected BackendService&MockObject $backendService;
6162
protected string $dataDir;
6263
protected CleaningDBConfig $dbConfig;
6364
protected static array $hookCalls;
6465
protected IUserMountCache&MockObject $mountCache;
6566
protected IEventDispatcher&MockObject $eventDispatcher;
67+
protected IAppConfig&MockObject $appConfig;
6668

6769
protected function setUp(): void {
6870
parent::setUp();
@@ -77,6 +79,7 @@ protected function setUp(): void {
7779

7880
$this->mountCache = $this->createMock(IUserMountCache::class);
7981
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
82+
$this->appConfig = $this->createMock(IAppConfig::class);
8083

8184
// prepare BackendService mock
8285
$this->backendService = $this->createMock(BackendService::class);

apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ protected function setUp(): void {
7575
$this->groupManager,
7676
$this->mountCache,
7777
$this->eventDispatcher,
78+
$this->appConfig,
7879
);
7980
}
8081

0 commit comments

Comments
 (0)