mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
Remove oc_storages entries after removing ext storages
When removing external storages, either system-wide or user-wide, automatically remove the matching oc_storages and oc_filecache entries. This can only work if the backend configuration doesn't contain any substitution variable $user in which case the storage id cannot be computed, so this case is ignored for now.
This commit is contained in:
parent
3413b76631
commit
bbebffb60c
3 changed files with 94 additions and 4 deletions
|
|
@ -550,6 +550,21 @@ abstract class StoragesService {
|
|||
$this->writeConfig($allStorages);
|
||||
|
||||
$this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount);
|
||||
|
||||
// delete oc_storages entries and oc_filecache
|
||||
try {
|
||||
$rustyStorageId = $this->getRustyStorageIdFromConfig($deletedStorage);
|
||||
\OC\Files\Cache\Storage::remove($rustyStorageId);
|
||||
} catch (\Exception $e) {
|
||||
// can happen either for invalid configs where the storage could not
|
||||
// be instantiated or whenever $user vars where used, in which case
|
||||
// the storage id could not be computed
|
||||
\OCP\Util::writeLog(
|
||||
'files_external',
|
||||
'Exception: "' . $e->getMessage() . '"',
|
||||
\OCP\Util::ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -570,4 +585,30 @@ abstract class StoragesService {
|
|||
return (max(array_keys($allStorages)) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rusty storage id from oc_storages from the given storage config.
|
||||
*
|
||||
* @param StorageConfig $storageConfig
|
||||
* @return string rusty storage id
|
||||
*/
|
||||
private function getRustyStorageIdFromConfig(StorageConfig $storageConfig) {
|
||||
// if any of the storage options contains $user, it is not possible
|
||||
// to compute the possible storage id as we don't know which users
|
||||
// mounted it already (and we certainly don't want to iterate over ALL users)
|
||||
foreach ($storageConfig->getBackendOptions() as $value) {
|
||||
if (strpos($value, '$user') !== false) {
|
||||
throw new \Exception('Cannot compute storage id for deletion due to $user vars in the configuration');
|
||||
}
|
||||
}
|
||||
|
||||
// note: similar to ConfigAdapter->prepateStorageConfig()
|
||||
$storageConfig->getAuthMechanism()->manipulateStorageConfig($storageConfig);
|
||||
$storageConfig->getBackend()->manipulateStorageConfig($storageConfig);
|
||||
|
||||
$class = $storageConfig->getBackend()->getStorageClass();
|
||||
$storageImpl = new $class($storageConfig->getBackendOptions());
|
||||
|
||||
return $storageImpl->getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,18 +216,57 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
|||
$this->service->updateStorage($storage);
|
||||
}
|
||||
|
||||
public function testDeleteStorage() {
|
||||
public function deleteStorageDataProvider() {
|
||||
return [
|
||||
// regular case, can properly delete the oc_storages entry
|
||||
[
|
||||
[
|
||||
'share' => 'share',
|
||||
'host' => 'example.com',
|
||||
'user' => 'test',
|
||||
'password' => 'testPassword',
|
||||
'root' => 'someroot',
|
||||
],
|
||||
'smb::test@example.com//share//someroot/',
|
||||
0
|
||||
],
|
||||
// special case with $user vars, cannot auto-remove the oc_storages entry
|
||||
[
|
||||
[
|
||||
'share' => 'share',
|
||||
'host' => 'example.com',
|
||||
'user' => '$user',
|
||||
'password' => 'testPassword',
|
||||
'root' => 'someroot',
|
||||
],
|
||||
'smb::someone@example.com//share//someroot/',
|
||||
1
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider deleteStorageDataProvider
|
||||
*/
|
||||
public function testDeleteStorage($backendOptions, $rustyStorageId, $expectedCountAfterDeletion) {
|
||||
$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
|
||||
$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
|
||||
$storage = new StorageConfig(255);
|
||||
$storage->setMountPoint('mountpoint');
|
||||
$storage->setBackend($backend);
|
||||
$storage->setAuthMechanism($authMechanism);
|
||||
$storage->setBackendOptions(['password' => 'testPassword']);
|
||||
$storage->setBackendOptions($backendOptions);
|
||||
|
||||
$newStorage = $this->service->addStorage($storage);
|
||||
$this->assertEquals(1, $newStorage->getId());
|
||||
|
||||
// manually trigger storage entry because normally it happens on first
|
||||
// access, which isn't possible within this test
|
||||
$storageCache = new \OC\Files\Cache\Storage($rustyStorageId);
|
||||
|
||||
// get numeric id for later check
|
||||
$numericId = $storageCache->getNumericId();
|
||||
|
||||
$newStorage = $this->service->removeStorage(1);
|
||||
|
||||
$caught = false;
|
||||
|
|
@ -238,6 +277,13 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
// storage id was removed from oc_storages
|
||||
$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
|
||||
$storageCheckQuery = $qb->select('*')
|
||||
->from('storages')
|
||||
->where($qb->expr()->eq('numeric_id', $qb->expr()->literal($numericId)));
|
||||
$this->assertCount($expectedCountAfterDeletion, $storageCheckQuery->execute()->fetchAll());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -138,8 +138,11 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
|||
$this->assertEmpty(self::$hookCalls);
|
||||
}
|
||||
|
||||
public function testDeleteStorage() {
|
||||
parent::testDeleteStorage();
|
||||
/**
|
||||
* @dataProvider deleteStorageDataProvider
|
||||
*/
|
||||
public function testDeleteStorage($backendOptions, $rustyStorageId, $expectedCountAfterDeletion) {
|
||||
parent::testDeleteStorage($backendOptions, $rustyStorageId, $expectedCountAfterDeletion);
|
||||
|
||||
// hook called once for user (first one was during test creation)
|
||||
$this->assertHookCall(
|
||||
|
|
|
|||
Loading…
Reference in a new issue