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

fix: Make user removal more resilient #47896

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

susnux
Copy link
Contributor

@susnux susnux commented Sep 11, 2024

Summary

Currently there is a problem if an exception is thrown in User::delete, because at that point the user is already removed from the backend, but not all data is deleted.

There is no way to recover from this state, as the user is gone no information is available anymore. This means the data is still available on the server but can not removed by any API anymore.

The solution here is to first set a flag and backup the user home, this can be used to recover failed user deletions in a way the delete can be re-tried.

Discussion

I am not 100% sure this is the best way, but as out API needs real user instances to delete user data, I think we need to go with the "FailedUsersBackend".
I tested this with injecting various exceptions in random places in the User::delete method and then let the background job cleanup the state. In my test cases this worked as expected.

Checklist

@susnux susnux force-pushed the fix/resiliant-user-removal branch 2 times, most recently from e58b96c to b714280 Compare September 11, 2024 14:51
@susnux susnux marked this pull request as ready for review September 11, 2024 15:00
@susnux susnux added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Sep 11, 2024
@susnux
Copy link
Contributor Author

susnux commented Sep 11, 2024

@blizzz I think you got a point here, we need to cover the case where backend->deleteUser threw an exception.
(if it returned we are always in a defined state)

Copy link
Member

@blizzz blizzz left a comment

Choose a reason for hiding this comment

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

Not tested, but looking ok

lib/private/User/FailedUsersBackend.php Outdated Show resolved Hide resolved
@blizzz

This comment was marked as resolved.

@blizzz

This comment was marked as resolved.

@susnux

This comment was marked as resolved.

lib/private/User/User.php Outdated Show resolved Hide resolved
lib/private/User/User.php Outdated Show resolved Hide resolved
$this->config->setUserValue($this->uid, 'core', 'deleted.backup-home', $this->getHome());

// Try to delete the user on the backend
$result = $this->backend?->deleteUser($this->uid);
Copy link
Contributor

Choose a reason for hiding this comment

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

In what situation is $this->backend null?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be honest: No idea. The backend is not required in the constructor and there are some code places where the user is constructed without any backend.

So two ways:

  1. Make this null safe as is now
  2. Or assert the backend is set and fail if not.

lib/private/User/User.php Outdated Show resolved Hide resolved
lib/private/User/User.php Outdated Show resolved Hide resolved
lib/private/User/BackgroundJobs/CleanupDeletedUsers.php Outdated Show resolved Hide resolved
@come-nc
Copy link
Contributor

come-nc commented Sep 12, 2024

I like the idea, not sure I like the fact that it runs daily.

@susnux
Copy link
Contributor Author

susnux commented Sep 19, 2024

I like the idea, not sure I like the fact that it runs daily.

It simply skips if there is nothing to do, otherwise it only does things in the maintenance window.

Currently there is a problem if an exception is thrown in `User::delete`,
because at that point the user is already removed from the backend,
but not all data is deleted.

There is no way to recover from this state, as the user is gone no information is available anymore.
This means the data is still available on the server but can not removed by any API anymore.

The solution here is to first set a flag and backup the user home,
this can be used to recover failed user deletions in a way the delete can be re-tried.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
@susnux
Copy link
Contributor Author

susnux commented Sep 24, 2024

/backport to stable30

@susnux
Copy link
Contributor Author

susnux commented Sep 24, 2024

/backport to stable29

@susnux
Copy link
Contributor Author

susnux commented Sep 24, 2024

/backport to stable28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

User data not deleted if User::delete failed
4 participants