fix(files_sharing): skip unresolvable share recipients - #62368
Conversation
| @@ -135,7 +136,17 @@ private function markOrRun(IUser $user, callable $callback): void { | |||
| $elapsed = $now - $this->firstRun; | |||
|
|
|||
| if ($this->cutOffMarkTime === -1.0 || $elapsed < $this->cutOffMarkTime) { | |||
There was a problem hiding this comment.
I thought === on float was not possible 🤔 Should this be < 0? (unrelated to this PR)
| // A share recipient may reference a user id that no backend can resolve anymore | ||
| // (e.g. with LazyUser::getUID()) - like remnant / incorrectly removed user. | ||
| // Skip this recipient instead of aborting the share operation. | ||
| $this->logger->warning( |
There was a problem hiding this comment.
I think debug level is enough. Also, no need to specify 'app' in the logger context, that’s automatically injected.
There was a problem hiding this comment.
Given the plausible ticket scenario (deleted/fake/unresolvable user is missing a share), agree that debug is probably enough
Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
d2ed18f to
847501c
Compare
|
I opened #62791 for another issue but of the same kind. |
Tested with my reproduction steps, sadly it doesn't get caught on your branch: {"reqId":"UgIT9iJaKsrzp4ZpNtzC","level":3,"time":"2026-08-03T17:01:00+00:00","remoteAddr":"192.168.21.9","user":"admin","app":"no app in context","method":"POST","url":"/ocs/v2.php/apps/files_sharing/api/v1/shares","scriptName":"/ocs/v2.php","message":"Error while sending 'share created' event","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36","version":"35.0.0.1","exception":{"Exception":"OC\\User\\NoUserException","Message":"Backends provided no user object","Code":0,"Trace":[{"function":"getUserFolder","class":"OC\\Files\\Node\\Root","type":"->","args":["bob2"]},{"file":"/var/www/html/lib/private/Files/Node/LazyFolder.php","line":67,"function":"call_user_func_array","args":[[{"__class__":"OC\\Files\\Node\\Root"},"getUserFolder"],["bob2"]]},{"file":"/var/www/html/lib/private/Files/Node/LazyRoot.php","line":41,"function":"__call","class":"OC\\Files\\Node\\LazyFolder","type":"->","args":["getUserFolder",["bob2"]]},{"file":"/var/www/html/apps/files_sharing/lib/ShareTargetValidator.php","line":70,"function":"getUserFolder","class":"OC\\Files\\Node\\LazyRoot","type":"->","args":["bob2"]},{"file":"/var/www/html/apps/files_sharing/lib/ShareRecipientUpdater.php","line":77,"function":"verifyMountPoint","class":"OCA\\Files_Sharing\\ShareTargetValidator","type":"->","args":["*** sensitive parameters replaced ***","*** sensitive parameters replaced ***",{"__class__":"Closure"},["*** sensitive parameters replaced ***"]]},{"file":"/var/www/html/apps/files_sharing/lib/Listener/SharesUpdatedListener.php","line":98,"function":"updateForAddedShare","class":"OCA\\Files_Sharing\\ShareRecipientUpdater","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/apps/files_sharing/lib/Listener/SharesUpdatedListener.php","line":138,"function":"{closure:OCA\\Files_Sharing\\Listener\\SharesUpdatedListener::handle():97}","class":"OCA\\Files_Sharing\\Listener\\SharesUpdatedListener","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/apps/files_sharing/lib/Listener/SharesUpdatedListener.php","line":97,"function":"markOrRun","class":"OCA\\Files_Sharing\\Listener\\SharesUpdatedListener","type":"->","args":["*** sensitive parameters replaced ***",{"__class__":"Closure"}]},{"file":"/var/www/html/lib/private/EventDispatcher/ServiceEventListener.php","line":57,"function":"handle","class":"OCA\\Files_Sharing\\Listener\\SharesUpdatedListener","type":"->","args":[{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"}]},{"file":"/var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php","line":220,"function":"__invoke","class":"OC\\EventDispatcher\\ServiceEventListener","type":"->","args":[{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"},"OCP\\Share\\Events\\ShareCreatedEvent",{"__class__":"Symfony\\Component\\EventDispatcher\\EventDispatcher"}]},{"file":"/var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php","line":56,"function":"callListeners","class":"Symfony\\Component\\EventDispatcher\\EventDispatcher","type":"->","args":[[{"__class__":"Closure"},{"__class__":"Closure"},{"__class__":"Closure"},{"__class__":"Closure"},{"__class__":"Closure"},"And 5 more entries, set log level to debug to see all entries"],"OCP\\Share\\Events\\ShareCreatedEvent",{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"}]},{"file":"/var/www/html/lib/private/EventDispatcher/EventDispatcher.php","line":74,"function":"dispatch","class":"Symfony\\Component\\EventDispatcher\\EventDispatcher","type":"->","args":[{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"},"OCP\\Share\\Events\\ShareCreatedEvent"]},{"file":"/var/www/html/lib/private/EventDispatcher/EventDispatcher.php","line":87,"function":"dispatch","class":"OC\\EventDispatcher\\EventDispatcher","type":"->","args":["OCP\\Share\\Events\\ShareCreatedEvent",{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"}]},{"file":"/var/www/html/lib/private/Share20/Manager.php","line":1897,"function":"dispatchTyped","class":"OC\\EventDispatcher\\EventDispatcher","type":"->","args":[{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"}]},{"file":"/var/www/html/lib/private/Share20/Manager.php","line":637,"function":"dispatchEvent","class":"OC\\Share20\\Manager","type":"->","args":[{"__class__":"OCP\\Share\\Events\\ShareCreatedEvent"},"share created"]},{"file":"/var/www/html/apps/files_sharing/lib/Controller/ShareAPIController.php","line":813,"function":"createShare","class":"OC\\Share20\\Manager","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/lib/private/AppFramework/Http/Dispatcher.php","line":172,"function":"createShare","class":"OCA\\Files_Sharing\\Controller\\ShareAPIController","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/lib/private/AppFramework/Http/Dispatcher.php","line":80,"function":"executeController","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->","args":[{"__class__":"OCA\\Files_Sharing\\Controller\\ShareAPIController"},"createShare"]},{"file":"/var/www/html/lib/private/AppFramework/App.php","line":138,"function":"dispatch","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->","args":[{"__class__":"OCA\\Files_Sharing\\Controller\\ShareAPIController"},"createShare"]},{"file":"/var/www/html/lib/private/Route/Router.php","line":324,"function":"main","class":"OC\\AppFramework\\App","type":"::","args":["OCA\\Files_Sharing\\Controller\\ShareAPIController","createShare",{"__class__":"OC\\AppFramework\\DependencyInjection\\DIContainer"},{"_route":"ocs.files_sharing.shareapi.createshare"}]},{"file":"/var/www/html/ocs/v1.php","line":78,"function":"match","class":"OC\\Route\\Router","type":"->","args":["/ocsapp/apps/files_sharing/api/v1/shares"]},{"file":"/var/www/html/ocs/v2.php","line":10,"args":["/var/www/html/ocs/v1.php"],"function":"require_once"}],"File":"/var/www/html/lib/private/Files/Node/Root.php","Line":325,"message":"Error while sending 'share created' event","exception":"{\"class\":\"OC\\User\\NoUserException\",\"message\":\"Backends provided no user object\",\"code\":0,\"file\":\"/var/www/html/lib/private/Files/Node/Root.php:325\",\"trace\":\"#0 [internal function]: OC\\Files\\Node\\Root->getUserFolder('bob2')\\n#1 /var/www/html/lib/private/Files/Node/LazyFolder.php(67): call_user_func_array(Array, Array)\\n#2 /var/www/html/lib/private/Files/Node/LazyRoot.php(41): OC\\Files\\Node\\LazyFolder->__call('getUserFolder', Array)\\n#3 /var/www/html/apps/files_sharing/lib/ShareTargetValidator.php(70): OC\\Files\\Node\\LazyRoot->getUserFolder('bob2')\\n#4 /var/www/html/apps/files_sharing/lib/ShareRecipientUpdater.php(77): OCA\\Files_Sharing\\ShareTargetValidator->verifyMountPoint(Object(OC\\User\\LazyUser), Object(OC\\Share20\\Share), Object(Closure), Array)\\n#5 /var/www/html/apps/files_sharing/lib/Listener/SharesUpdatedListener.php(98): OCA\\Files_Sharing\\ShareRecipientUpdater->updateForAddedShare(Object(OC\\User\\LazyUser), Object(OC\\Share20\\Share))\\n#6 /var/www/html/apps/files_sharing/lib/Listener/SharesUpdatedListener.php(138): OCA\\Files_Sharing\\Listener\\SharesUpdatedListener->{closure:OCA\\Files_Sharing\\Listener\\SharesUpdatedListener::handle():97}()\\n#7 /var/www/html/apps/files_sharing/lib/Listener/SharesUpdatedListener.php(97): OCA\\Files_Sharing\\Listener\\SharesUpdatedListener->markOrRun(Object(OC\\User\\LazyUser), Object(Closure))\\n#8 /var/www/html/lib/private/EventDispatcher/ServiceEventListener.php(57): OCA\\Files_Sharing\\Listener\\SharesUpdatedListener->handle(Object(OCP\\Share\\Events\\ShareCreatedEvent))\\n#9 /var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php(220): OC\\EventDispatcher\\ServiceEventListener->__invoke(Object(OCP\\Share\\Events\\ShareCreatedEvent), 'OCP\\\\Share\\\\Event...', Object(Symfony\\Component\\EventDispatcher\\EventDispatcher))\\n#10 /var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php(56): Symfony\\Component\\EventDispatcher\\EventDispatcher->callListeners(Array, 'OCP\\\\Share\\\\Event...', Object(OCP\\Share\\Events\\ShareCreatedEvent))\\n#11 /var/www/html/lib/private/EventDispatcher/EventDispatcher.php(74): Symfony\\Component\\EventDispatcher\\EventDispatcher->dispatch(Object(OCP\\Share\\Events\\ShareCreatedEvent), 'OCP\\\\Share\\\\Event...')\\n#12 /var/www/html/lib/private/EventDispatcher/EventDispatcher.php(87): OC\\EventDispatcher\\EventDispatcher->dispatch('OCP\\\\Share\\\\Event...', Object(OCP\\Share\\Events\\ShareCreatedEvent))\\n#13 /var/www/html/lib/private/Share20/Manager.php(1897): OC\\EventDispatcher\\EventDispatcher->dispatchTyped(Object(OCP\\Share\\Events\\ShareCreatedEvent))\\n#14 /var/www/html/lib/private/Share20/Manager.php(637): OC\\Share20\\Manager->dispatchEvent(Object(OCP\\Share\\Events\\ShareCreatedEvent), 'share created')\\n#15 /var/www/html/apps/files_sharing/lib/Controller/ShareAPIController.php(813): OC\\Share20\\Manager->createShare(Object(OC\\Share20\\Share))\\n#16 /var/www/html/lib/private/AppFramework/Http/Dispatcher.php(172): OCA\\Files_Sharing\\Controller\\ShareAPIController->createShare('/Talk/vertical ...', 19, 10, '3579626860', NULL, '', NULL, NULL, '', '', NULL, NULL)\\n#17 /var/www/html/lib/private/AppFramework/Http/Dispatcher.php(80): OC\\AppFramework\\Http\\Dispatcher->executeController(Object(OCA\\Files_Sharing\\Controller\\ShareAPIController), 'createShare')\\n#18 /var/www/html/lib/private/AppFramework/App.php(138): OC\\AppFramework\\Http\\Dispatcher->dispatch(Object(OCA\\Files_Sharing\\Controller\\ShareAPIController), 'createShare')\\n#19 /var/www/html/lib/private/Route/Router.php(324): OC\\AppFramework\\App::main('OCA\\\\Files_Shari...', 'createShare', Object(OC\\AppFramework\\DependencyInjection\\DIContainer), Array)\\n#20 /var/www/html/ocs/v1.php(78): OC\\Route\\Router->match('/ocsapp/apps/fi...')\\n#21 /var/www/html/ocs/v2.php(10): require_once('/var/www/html/o...')\\n#22 {main}\"}","CustomMessage":"Error while sending 'share created' event"}} |
|
Would be good to merge for the maintenance release RC this week? |
Summary
in
SharesUpdatedListener, a share recipient may reference a user id that no backend can resolve anymore (e.g. with LazyUser::getUID()) - like remnant / incorrectly removed user.Example: Talk application supplies LazyUsers from oc_talk_attendees table, which can get desynced from the user backend (e.g. LDAP entries)
Skip this recipient instead of aborting the share operation resolve the issue. As listener is running as a post-effect, and share is already created (at least to the room -> to the group), it should be a safe reason to catch and skip?
To test:
TODO
OC\User\NoUserException?Checklist
3. to review, feature component)stable32)AI (if applicable)