Skip to content

Commit

Permalink
Merge pull request #30712 from owncloud/user-delete-storage-issue
Browse files Browse the repository at this point in the history
Remove user from the storage setting or storage when user is deleted
  • Loading branch information
Vincent Petry authored Jul 16, 2018
2 parents 70b57d8 + 3f576a5 commit a4b2858
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 1 deletion.
33 changes: 33 additions & 0 deletions lib/private/Files/External/Service/GlobalStoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use OCP\Files\External\IStorageConfig;
use OCP\Files\External\IStoragesBackendService;
use OCP\Files\External\Service\IGlobalStoragesService;
use OCP\IUser;

/**
* Service class to manage global external storages
Expand Down Expand Up @@ -182,4 +183,36 @@ public function getStorageForAllUsers() {

return \array_combine($keys, $configs);
}

/**
* Deletes the external storages mounted to the user
*
* @param IUser $user
* @return bool
*/
public function deleteAllForUser($user) {
$userId = $user->getUID();
$result = false;
//Get all valid storages
$mounts = $this->getStorages();
foreach ($mounts as $mount) {
$applicableUsers = $mount->getApplicableUsers();
$id = $mount->getId();
if (\in_array($userId, $applicableUsers, true)) {
if (\count($applicableUsers) === 1) {
//As this storage is associated only with this user.
$this->removeStorage($id);
$result = true;
} else {
$storage = $this->getStorage($id);
$userIndex = \array_search($userId, $applicableUsers, true);
unset($applicableUsers[$userIndex]);
$storage->setApplicableUsers($applicableUsers);
$this->updateStorage($storage);
$result = true;
}
}
}
return $result;
}
}
20 changes: 20 additions & 0 deletions lib/private/Files/External/Service/UserStoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use OC\Files\Filesystem;

use OCP\Files\Config\IUserMountCache;
use OCP\IUser;
use OCP\IUserSession;

use OCP\Files\External\IStorageConfig;
Expand Down Expand Up @@ -56,6 +57,7 @@ public function __construct(
IUserMountCache $userMountCache
) {
$this->userSession = $userSession;
$this->userMountCache = $userMountCache;
parent::__construct($backendService, $dbConfig, $userMountCache);
}

Expand Down Expand Up @@ -140,4 +142,22 @@ public function getVisibilityType() {
protected function isApplicable(IStorageConfig $config) {
return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === IStorageConfig::MOUNT_TYPE_PERSONAl;
}

/**
* Deletes the storages mounted to a user
* @param IUser $user
* @return bool
*/
public function deleteAllMountsForUser(IUser $user) {
$getUserMounts = $this->userMountCache->getMountsForUser($user);
$result = false;
if (\count($getUserMounts) > 0) {
foreach ($getUserMounts as $userMount) {
$id = $userMount->getStorageId();
$this->userMountCache->removeUserStorageMount($id, $user->getUID());
$result = true;
}
}
return $result;
}
}
6 changes: 5 additions & 1 deletion lib/private/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
use OCP\IUserBackend;
use OCP\IUserSession;
use OCP\User\IChangePasswordBackend;
use OCP\UserInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;

Expand Down Expand Up @@ -226,6 +225,11 @@ public function delete() {
// Delete the user's keys in preferences
\OC::$server->getConfig()->deleteAllUserValues($this->getUID());

// Delete all mount points for user
\OC::$server->getUserStoragesService()->deleteAllMountsForUser($this);
//Delete external storage or remove user from applicableUsers list
\OC::$server->getGlobalStoragesService()->deleteAllForUser($this);

// Delete user files in /data/
if ($homePath !== false) {
// FIXME: this operates directly on FS, should use View instead...
Expand Down
8 changes: 8 additions & 0 deletions lib/public/Files/External/Service/IGlobalStoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,12 @@ interface IGlobalStoragesService extends IStoragesService {
* @since 10.0
*/
public function getStorageForAllUsers();

/**
* Deletes the external storages mounted to the user
* @param \OCP\IUser $user
* @return bool
* @since 10.0.10
*/
public function deleteAllForUser($user);
}
7 changes: 7 additions & 0 deletions lib/public/Files/External/Service/IUserStoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,11 @@
* @since 10.0
*/
interface IUserStoragesService extends IStoragesService {
/**
* Deletes the storages mounted to a user
* @param \OCP\IUser $user
* @return bool
* @since 10.0.10
*/
public function deleteAllMountsForUser(\OCP\IUser $user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php
/**
* @author Sujith Haridasan <sharidasan@owncloud.com>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Test\Files\External\Service;

use OC\Files\Config\UserMountCache;
use OC\Files\External\Service\DBConfigService;
use OC\Files\External\Service\GlobalStoragesService;
use OC\Files\External\StoragesBackendService;
use OCA\Files_External\Lib\Backend\Backend;
use OCP\IUser;
use Test\TestCase;

/**
* Class GlobalStoragesServiceDeleteUser
*
* @group DB
* @package Test\Files\External\Service
*/
class GlobalStoragesServiceDeleteUserTest extends TestCase {
public function setUp() {
parent::setUp();
}

public function tearDown() {
parent::tearDown();

//Remove all global storages created
$globalStorageService = \OC::$server->getGlobalStoragesService();
foreach ($globalStorageService->getAllStorages() as $storage) {
$storageId = $storage->getId();
$globalStorageService->removeStorage($storageId);
}
}

public function providesDeleteAllUser() {
return [
[
[
[
'applicableUsers' => ['user1', 'user2'],
'applicableGroups' => ['group1'],
'priority' => 12,
'authMechanism' => 'identifier:\Auth\Mechanism',
'storageClass' => 'OC\Files\Storage\DAV',
'backendIdentifier' => 'identifier:\Test\Files\External\Backend\DummyBackend',
'backendOptions' => [
'host' => 'http://localhost',
'root' => 'test',
'secure' => 'false',
'user' => 'foo',
'password' => 'foo'
]
],
[
'applicableUsers' => ['user1', 'user3'],
'applicableGroups' => [],
'priority' => 13,
'authMechanism' => 'identifier:\Auth\Mechanism',
'storageClass' => 'OC\Files\Storage\DAV',
'backendIdentifier' => 'identifier:\Test\Files\External\Backend\DummyBackend2',
'backendOptions' => [
'host' => 'http://localhost',
'root' => 'test1',
'secure' => 'false',
'user' => 'foo',
'password' => 'foo'
]
],
[
'applicableUsers' => ['user1', 'user4'],
'applicableGroups' => [],
'priority' => 14,
'storageClass' => 'OC\Files\Storage\DAV',
'authMechanism' => 'identifier:\Auth\Mechanism',
'backendIdentifier' => 'identifier:\Test\Files\External\Backend\DummyBackend2',
'backendOptions' => [
'host' => 'http://localhost',
'root' => 'test2',
'secure' => 'false',
'user' => 'foo',
'password' => 'foo'
]
],
//This storage shouldn't be available
[
'applicableUsers' => ['user1'],
'applicableGroups' => [],
'priority' => 15,
'authMechanism' => 'identifier:\Auth\Mechanism',
'storageClass' => 'OC\Files\Storage\DAV',
'backendIdentifier' => 'identifier:\Test\Files\External\Backend\DummyBackend2',
'backendOptions' => [
'host' => 'http://localhost',
'root' => 'test3',
'secure' => 'false',
'user' => 'foo',
'password' => 'foo'
]
],
], 'user1'
]
];
}

/**
* @dataProvider providesDeleteAllUser
* @param $storageParams
*/
public function testDeleteAllForUser($storageParams, $userId) {
$backendService = new StoragesBackendService(\OC::$server->getConfig());
$dbConfigService = new DBConfigService(\OC::$server->getDatabaseConnection(), \OC::$server->getCrypto());
$userManager = \OC::$server->getUserManager();
$userMountCache = new UserMountCache(\OC::$server->getDatabaseConnection(), $userManager, \OC::$server->getLogger());
$service = new GlobalStoragesService($backendService, $dbConfigService, $userMountCache);

$storageIds = [];
foreach ($storageParams as $storageParam) {
$backend = new Backend();
$backend->setIdentifier($storageParam['backendIdentifier']);
$backendService->registerBackend($backend);
$storageConfig = $service->createStorage('/foo/',
$storageParam['backendIdentifier'], $storageParam['authMechanism'],
$storageParam['backendOptions'], null,
$storageParam['applicableUsers'], $storageParam['applicableGroups'],
$storageParam['priority']);
$storageConfig->setBackend($backend);
$backend->setStorageClass($storageParam['storageClass']);

$newStorage = $service->addStorage($storageConfig);
$storageIds[] = $newStorage->getId();
}

$user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn($userId);

$this->assertTrue($service->deleteAllForUser($user));

$storages = $service->getStorages();
$newStorageIds = [];
foreach ($storages as $storage) {
$users = $storage->getApplicableUsers();
$this->assertFalse(\in_array($userId, $users, true));
$this->assertTrue(\in_array($storage->getId(), $storageIds, true));
$newStorageIds[] = $storage->getId();
}
$missingStorageId = \array_pop($storageIds);
$this->assertFalse(\in_array($missingStorageId, $newStorageIds, true));
}
}
62 changes: 62 additions & 0 deletions tests/lib/Files/External/Service/UserStoragesServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@
*/
namespace Test\Files\External\Service;

use OC\Files\Config\UserMountCache;
use OC\Files\External\Service\GlobalStoragesService;
use OC\Files\External\Service\UserStoragesService;
use OC\Files\External\StorageConfig;
use OC\Files\Filesystem;
use OC\Files\Mount\MountPoint;
use OCP\Files\External\IStorageConfig;
use OCP\Files\External\Service\IStoragesService;
use OCP\ILogger;
use OCP\IUser;
use Test\Traits\UserTrait;

/**
Expand Down Expand Up @@ -204,4 +208,62 @@ public function testGetAdminStorage() {

$this->service->getStorage($newStorage->getId());
}

private function getStorage($storageId, $rootId) {
$storageCache = $this->getMockBuilder('\OC\Files\Cache\Storage')
->disableOriginalConstructor()
->getMock();
$storageCache->expects($this->any())
->method('getNumericId')
->will($this->returnValue($storageId));

$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
->disableOriginalConstructor()
->getMock();
$cache->expects($this->any())
->method('getId')
->will($this->returnValue($rootId));

$storage = $this->getMockBuilder('\OC\Files\Storage\Storage')
->disableOriginalConstructor()
->getMock();
$storage->expects($this->any())
->method('getStorageCache')
->will($this->returnValue($storageCache));
$storage->expects($this->any())
->method('getCache')
->will($this->returnValue($cache));

return $storage;
}

public function testDeleteAllMountsForUser() {
$storage1 = $this->getStorage(10, 20);
$storage2 = $this->getStorage(12, 22);

$mount1 = new MountPoint($storage1, '/foo/');
$mount2 = new MountPoint($storage2, '/bar/');

$dbConnection = \OC::$server->getDatabaseConnection();
$userManager = \OC::$server->getUserManager();
$logger = $this->createMock(ILogger::class);
$userMountCache = new UserMountCache($dbConnection, $userManager, $logger);
$user1 = $userManager->createUser('user1', 'user1');
$user2 = $userManager->createUser('user2', 'user2');

$userMountCache->registerMounts($user1, [$mount1, $mount2]);

$userMountCache->registerMounts($user2, [$mount2]);

$backendService = \OC::$server->getStoragesBackendService();
$userSession = \OC::$server->getUserSession();
$this->service = new UserStoragesService($backendService, $this->dbConfig, $userSession, $userMountCache);
$this->assertTrue($this->service->deleteAllMountsForUser($user1));
$storarge1Result1 = $userMountCache->getMountsForStorageId(10);
$storarge1Result2 = $userMountCache->getMountsForStorageId(12);
$this->assertEquals(0, \count($storarge1Result1));
$this->assertEquals(1, \count($storarge1Result2));
$this->assertEquals(12, $storarge1Result2[0]->getStorageId());
$this->assertEquals('/bar/', $storarge1Result2[0]->getMountPoint());
}
}

0 comments on commit a4b2858

Please sign in to comment.