Skip to content
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

Remove user from the storage setting or storage when user is deleted #30712

Merged
merged 1 commit into from
Jul 16, 2018

Conversation

sharidas
Copy link
Contributor

@sharidas sharidas commented Mar 6, 2018

Remove user from the storage if there are multiple
users associated with the storage during deletion
of the user. Else remove the storage when user is
deleted, since the storage is only associated with
the user being deleted.

Signed-off-by: Sujith H sharidasan@owncloud.com

Description

Remove user from the external storage list when there are multiple users applicable users for the storage, during deletion of user. Else remove the storage as the user which is being deleted is the only storage associated with the user.

Related Issue

#30694

Motivation and Context

This change would help to clean up the external storage when a user is being deleted.

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@sharidas sharidas self-assigned this Mar 6, 2018
@@ -227,6 +226,24 @@ public function delete() {
// Delete the user's keys in preferences
\OC::$server->getConfig()->deleteAllUserValues($this->getUID());

//Delete external storage or remove user from applicableUsers list
foreach (\OC::$server->getUserGlobalStoragesService()->getStorageForAllUsers() as $storageForAllUser) {
Copy link
Contributor

Choose a reason for hiding this comment

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

did you try with getUserStoragesService() instead ? this would be more direct and give you the whole list without the need to filter.
However one problem is that this service works with the user from the session, might need to refactor it in a way that allows creating/querying it for a given user.

if (in_array($this->getUID(), $applicableUsers, true)) {
if (count($applicableUsers) === 1) {
//As this storage is associated only with this user.
\OC::$server->getGlobalStoragesService()->removeStorage($id);
Copy link
Contributor

Choose a reason for hiding this comment

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

but actually you might be right, this removes storages created by an admin and applied only for a user, so maybe this approach is ok

@PVince81
Copy link
Contributor

PVince81 commented Mar 6, 2018

I wonder if this logic could be put in a method of one of the services. But it seems the services don't know from each other yet. Does deleting a storage not work from the "UserGlobalStoragesService" ?

@codecov
Copy link

codecov bot commented Mar 6, 2018

Codecov Report

Merging #30712 into master will increase coverage by 0.13%.
The diff coverage is 100%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master   #30712      +/-   ##
============================================
+ Coverage     63.59%   63.72%   +0.13%     
- Complexity    18556    18563       +7     
============================================
  Files          1169     1169              
  Lines         69606    69631      +25     
  Branches       1264     1264              
============================================
+ Hits          44267    44374     +107     
+ Misses        24970    24888      -82     
  Partials        369      369
Flag Coverage Δ Complexity Δ
#javascript 52.59% <ø> (ø) 0 <ø> (ø) ⬇️
#phpunit 65% <100%> (+0.14%) 18563 <7> (+7) ⬆️
Impacted Files Coverage Δ Complexity Δ
...ate/Files/External/Service/UserStoragesService.php 100% <100%> (ø) 14 <3> (+3) ⬆️
lib/private/User/User.php 87.93% <100%> (+0.14%) 67 <0> (ø) ⬇️
...e/Files/External/Service/GlobalStoragesService.php 89.69% <100%> (+1.22%) 18 <4> (+4) ⬆️
lib/private/Security/CertificateManager.php 93.33% <0%> (-1.12%) 36% <0%> (ø)
lib/private/Files/Storage/DAV.php 81.09% <0%> (+0.42%) 0% <0%> (ø) ⬇️
lib/private/legacy/app.php 64.75% <0%> (+0.44%) 180% <0%> (ø) ⬇️
...private/Files/External/Service/StoragesService.php 93.68% <0%> (+0.48%) 62% <0%> (ø) ⬇️
lib/private/Server.php 86.36% <0%> (+1.07%) 253% <0%> (ø) ⬇️
.../private/Files/External/StoragesBackendService.php 91.78% <0%> (+2.73%) 34% <0%> (ø) ⬇️
lib/public/Files/External/DefinitionParameter.php 83.01% <0%> (+3.77%) 23% <0%> (ø) ⬇️
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 00402f3...3f576a5. Read the comment docs.

@sharidas
Copy link
Contributor Author

sharidas commented Mar 6, 2018

Does deleting a storage not work from the "UserGlobalStoragesService" ?

If we use "getUserGlobalStoragesService", then the problem happens when ./occ user:delete is executed. The deletion of storage doesn't work and causes exception. The exception message is UserGlobalStoragesService writing is disallowed

@PVince81
Copy link
Contributor

PVince81 commented Mar 6, 2018

Yeah, UserGlobalStoragesService is designed for read-only use in the web UI and storage level, to find out all storages the current user has access to, whether configured globally or locally.

Another approach would be to simply have two calls: one for the local storages, maybe UserStoragesService->deleteAll() and another one GlobalStoragesService->deleteAllForUser($userId).

It would also make it easier to write unit tests as you'd mostly write tests for these two methods.

@sharidas sharidas force-pushed the user-delete-storage-issue branch 2 times, most recently from 0743cee to f69b77c Compare March 7, 2018 13:29
@@ -227,6 +226,9 @@ public function delete() {
// Delete the user's keys in preferences
\OC::$server->getConfig()->deleteAllUserValues($this->getUID());

//Delete external storage or remove user from applicableUsers list
\OC::$server->getGlobalStoragesService()->deleteAllForUser($this->getUID());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, the home storage gets deleted later as part of user deletion

however home storage is untouched by the any of the storagesservice which only operate on external storage currently

@sharidas sharidas changed the title [WIP] Remove user from the storage setting or storage when user is deleted Remove user from the storage setting or storage when user is deleted Mar 12, 2018
@mmattel
Copy link
Contributor

mmattel commented Jun 11, 2018

@sharidas any update on this ?

$storage = $this->makeStorageConfig($storageParams);
$this->service->addStorage($storage);
if (isset($storageParams['applicableUsers'])) {
$this->assertTrue($this->service->deleteAllForUser($storageParams['applicableUsers'][0]));
Copy link
Contributor

Choose a reason for hiding this comment

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

please also verify that the "applicable" value was properly set after deleteAllForUser and possibly other values. Checking for the return value is not enough to ensure the function is doing its job

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@PVince81 PVince81 added this to the development milestone Jun 12, 2018
*/
public function deleteAllForUser($userId) {
$result = false;
$mounts = $this->getStorageForAllUsers();
Copy link
Contributor

Choose a reason for hiding this comment

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

here I'm wondering about scalability: if there are 10000 users and each have a mount, we're querying all possible mounts, even the personal mounts of irrelevant users

I wonder if we should split this in two parts:

  1. get all personal mounts of said user, then remove said storages
    and
  2. get all system mounts (no personal mounts) and then filter applicable users as you did below

@butonic does that make sense or is the current solution sufficient for real-life scenarios ?

Copy link
Contributor

Choose a reason for hiding this comment

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

@sharidas let's go with the proposed approach to play it safe. Here I'm assuming that we already have the necessary API calls to retrieve this info.

Copy link
Contributor Author

@sharidas sharidas Jun 21, 2018

Choose a reason for hiding this comment

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

Two API's are found to get mounts for user:

Guess we can opt for the first one.

\array_shift($storageParams['applicableUsers']);
$this->assertEquals([], \array_diff($storageParams['applicableUsers'], $finalApplicableUsers));
} else {
$storages = \count($this->service->getAllStorages());
Copy link
Contributor

Choose a reason for hiding this comment

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

you should also make sure that non-relevant storages were not deleted and are still present
for this, create a few unrelated storages and check for these

you could use the "store their id" technique after creation then requery them to see if they still exist and confirm that the correct ones are gone

* Deletes the external storages mounted to the user
* @param $userId
* @return bool
* @since 10.0.8
Copy link
Contributor

Choose a reason for hiding this comment

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

set to 10.0.10

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

// 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->getUID());
Copy link
Contributor

Choose a reason for hiding this comment

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

be consistent: use either UID or user object

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Prefer to use user object. Considering future usage.

@sharidas sharidas force-pushed the user-delete-storage-issue branch 2 times, most recently from 4e584e1 to 7dd879f Compare June 25, 2018 12:44
@sharidas
Copy link
Contributor Author

I have created a new file in this PR, https://github.com/owncloud/core/pull/30712/files#diff-31407757e5ad52b7e7c4a81530bb4113. The reason why I created a new file is while playing with storageId, I found that GlobalStoragesServiceTest extens StoragesServiceTest and that was causing issues while testing. So I thought its better to separate this test in a separate file.

@sharidas sharidas force-pushed the user-delete-storage-issue branch 6 times, most recently from 86a229a to 795a085 Compare June 26, 2018 10:45
@sharidas
Copy link
Contributor Author

sharidas commented Jul 6, 2018

@PVince81 review required.

Copy link
Contributor

@PVince81 PVince81 left a comment

Choose a reason for hiding this comment

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

Looks good, there's only one additional adjustment needed to avoid performance issue by reading too many configs that aren't needed

public function deleteAllForUser($user) {
$userId = $user->getUID();
$result = false;
$mounts = $this->getStorageForAllUsers();
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems this method returns not only admin mounts but also personal mounts as it uses DBConfigService::getAllMounts() instead of getAdminMounts().

From reading the code further, it seems you'd need to call getAllStorages() or getStorages() which do call DBConfigService::getAdminMounts() through StorageService::readConfig()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove user from the storage if there are multiple
users associated with the storage during deletion
of the user. Else remove the storage when user is
deleted, since the storage is only associated with
the user being deleted.

Signed-off-by: Sujith H <sharidasan@owncloud.com>
@PVince81 PVince81 merged commit a4b2858 into master Jul 16, 2018
@PVince81 PVince81 deleted the user-delete-storage-issue branch July 16, 2018 12:11
@PVince81
Copy link
Contributor

@sharidas please backport

@phil-davis
Copy link
Contributor

@sharidas has this been backported?

@sharidas
Copy link
Contributor Author

sharidas commented Sep 4, 2018

@PVince81 @phil-davis

This has been backported. The commit in stable10 b6d79b3

The PR for stable10 branch : #32069

@lock lock bot locked as resolved and limited conversation to collaborators Sep 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants