Skip to content

Commit b30b8a4

Browse files
committed
fix(files_sharing): skip unresolvable share recipients
Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
1 parent 00ea746 commit b30b8a4

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

apps/files_sharing/lib/Listener/SharesUpdatedListener.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace OCA\Files_Sharing\Listener;
1010

11+
use OC\User\NoUserException;
1112
use OCA\Files_Sharing\AppInfo\Application;
1213
use OCA\Files_Sharing\Config\ConfigLexicon;
1314
use OCA\Files_Sharing\Event\UserShareAccessUpdatedEvent;
@@ -136,7 +137,14 @@ public function handle(Event $event): void {
136137
private function markOrRun(IUser $user, callable $callback): void {
137138
$start = floatval($this->clock->now()->format('U.u'));
138139
if ($this->cutOffMarkTime === -1.0 || $this->updatedTime < $this->cutOffMarkTime) {
139-
$callback();
140+
try {
141+
$callback();
142+
} catch (NoUserException $e) {
143+
// A share recipient may reference a user id that no backend can resolve anymore
144+
// (e.g. with LazyUser::getUID()) - like remnant / incorrectly removed user.
145+
// Skip this recipient instead of aborting the share operation.
146+
$this->logger->debug('Skipping share mount update for unresolvable user ' . $user->getUID(), ['exception' => $e]);
147+
}
140148
} else {
141149
$this->markUserForRefresh($user);
142150
}

apps/files_sharing/tests/SharesUpdatedListenerTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace OCA\Files_Sharing\Tests;
99

10+
use OC\User\NoUserException;
1011
use OCA\Files_Sharing\Config\ConfigLexicon;
1112
use OCA\Files_Sharing\Event\UserShareAccessUpdatedEvent;
1213
use OCA\Files_Sharing\Listener\SharesUpdatedListener;
@@ -115,6 +116,33 @@ public function testShareAddedFilterOwner() {
115116
$this->sharesUpdatedListener->handle($event);
116117
}
117118

119+
public function testShareAddedSkipsUnresolvableUser(): void {
120+
$share = $this->createMock(IShare::class);
121+
$user1 = $this->createUser('user1', '');
122+
$user2 = $this->createUser('user2', '');
123+
124+
$this->manager->method('getUsersForShare')
125+
->willReturn([$user1, $user2]);
126+
127+
$event = new ShareCreatedEvent($share);
128+
129+
// user1 is an orphaned recipient that no backend can resolve
130+
$this->shareRecipientUpdater
131+
->expects($this->exactly(2))
132+
->method('updateForAddedShare')
133+
->willReturnCallback(function (IUser $user) use ($user1): void {
134+
if ($user === $user1) {
135+
throw new NoUserException('Backends provided no user object');
136+
}
137+
});
138+
139+
// the failure is logged, not thrown
140+
$this->logger->expects($this->once())->method('debug');
141+
142+
// must not throw: user2 is still processed
143+
$this->sharesUpdatedListener->handle($event);
144+
}
145+
118146
public function testShareAccessUpdated() {
119147
$user1 = $this->createUser('user1', '');
120148
$user2 = $this->createUser('user2', '');

0 commit comments

Comments
 (0)