[Bug]: Group cache is not invalidated correctly, leading to shares not being accepted automatically #47712
Open
6 of 8 tasks
Labels
0. Needs triage
Pending check for reproducibility or if it fits our roadmap
29-feedback
bug
feature: sharing
feature: users and groups
Bug description
When a plugin such as user_oidc or nextcloud-oidc-login is used and groups are synchronizing via them, folder shares that are shared with a new group of that user are not accepted automatically. Instead, users have to accept them manually by checking the pending shares (
https://nextcloud.example.com/apps/files/pendingshares
), even though the settings to accept the shares automatically are all correct. This is described in issues in the respective plugins, namely nextcloud/user_oidc#827 and pulsejet/nextcloud-oidc-login#256.As described in the issues, this was working with Nextcloud 27.
Tracing the problem
However, those issues are only a symptom to an underlying problem with the caching of the user groups in the GroupManager. Consider the following (pseudoish) code:
This is what happens in both plugins and seems perfectly logic. Except, this leads to the shares not being accepted automatically.
The call to
getUserGroups
ultimately leads togetUserIdGroupIds
of the manager:server/lib/private/Group/Manager.php
Lines 374 to 386 in 6b85a3a
If the user hasn't been cached yet, their groups are loaded and stored in the cache.
Now, we add the user to a new group through a call to
addUser
:server/lib/private/Group/Group.php
Lines 149 to 172 in 6b85a3a
This adds the user to the group and notifies others through events before and after that.
The
UserAddedEvent
is handled by theUserAddedToGroupListener
from thefiles_sharing
app and gets all shares the user has access to from the share manager, to automatically accept them:server/apps/files_sharing/lib/Listener/UserAddedToGroupListener.php
Lines 47 to 57 in 6b85a3a
The share manager asks its providers and the call ends up in the
DefaultShareProvider
, which asks the group manager for the users groups again.server/lib/private/Share20/DefaultShareProvider.php
Line 897 in 6b85a3a
And at this point, the user is already in the user group cache of the group manager, but without the new group, so shares belonging to the new group are not returned yet and thus can also not be automatically accepted by the
UserAddedToGroupListener
.Only when the
postAddUser
event is fired in thegroup->addUser
function will the group manager clear the cache, but it's too late already.server/lib/private/Group/Manager.php
Lines 72 to 74 in 6b85a3a
Potential solutions
To fix this, the
cachedUserGroups
must be cleared correctly. Here are some options I though about.Before the user is added to the group
This is easy to implement by adding the following listener to the group manager:
I can confirm that this works and remediates the issue for now. Nevertheless, I think it could still be that some other class also listens to the
preAddUser
event and is executed after thepreAddUser
listener of the group manager. If that class would then call the group manager again to populate the cache (which doesn't seem to be the case right now, but might happen unknowingly in the future), we are back to the original problem.After the user is added to the group
This is how it's handled right now via the
postAddUser
event, but this is handled after the typeUserAddedEvent
and leads to the current issue.I think ideally, we would clear the cache right after the call to
$backend->addToGroup
to avoid that new calls to the group manager "poison" the cache before it can pick up the new group. But since the cache is an implementation detail of the concreteManager
class and not part of theIGroupManager
, we can't simply call something like$manager->invalidateCache
and have to rely on the event instead.Therefore, we either need to ensure that the group manager handles the
UserAddedEvent
first or add another event which for now is only listened to by the group manager to clean up the cache. The caching side effects should then be documented to ensure that users listen to theUserAddedEvent
if they need a consistent view on the groups.Extending the IGroupManager interface with a new function
We could somewhat expose the caching detail of the group manager into the interface and add a new function either to flush the cache or to get the groups without caching logic (which could default to calling the usual function if the concrete implementation doesn't support caching).
Steps to reproduce
user_oidc
or thenextcloud-oidc-login
plugin with your IdP and enable group provisioning.Alternatively, if you don't want to setup an OIDC plugin, you can modify the code of your Nextcloud to replicate the behavior by adding
$this->groupManager->getUserGroupIds($targetUser);
before this call toaddUser
:server/apps/provisioning_api/lib/Controller/UsersController.php
Lines 1433 to 1434 in 6b85a3a
Then, adding users to groups via the Nextcloud UI won't accept the shares automatically as well. Removing the line will make it work again.
Expected behavior
Shares should be accepted automatically if configured so.
But precisely, calling
getUserGroupIds
or similar before adding a user to a new group should not have unexpected side-effects like caches not being flushed correctly and later calls to get the users groups returning stale data.Nextcloud Server version
29
Operating system
None
PHP engine version
None
Web server
None
Database engine version
None
Is this bug present after an update or on a fresh install?
Fresh Nextcloud Server install
Are you using the Nextcloud Server Encryption module?
None
What user-backends are you using?
Configuration report
List of activated Apps
Nextcloud Signing status
Nextcloud Logs
No response
Additional info
No response
The text was updated successfully, but these errors were encountered: