Merge pull request #62368 from nextcloud/fix/18415/talk-share-fail-for-orphan-user

fix(files_sharing): skip unresolvable share recipients
pull/62932/head
Joas Schilling 2 weeks ago committed by GitHub
commit c857bb9292
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      apps/files_sharing/lib/Listener/SharesUpdatedListener.php
  2. 28
      apps/files_sharing/tests/SharesUpdatedListenerTest.php

@ -26,6 +26,7 @@ use OCP\Share\Events\ShareCreatedEvent;
use OCP\Share\Events\ShareMovedEvent;
use OCP\Share\Events\ShareTransferredEvent;
use OCP\Share\IManager;
use OCP\User\Exceptions\UserNotFoundException;
use Psr\Clock\ClockInterface;
use Psr\Log\LoggerInterface;
@ -135,7 +136,14 @@ class SharesUpdatedListener implements IEventListener {
$elapsed = $now - $this->firstRun;
if ($this->cutOffMarkTime === -1.0 || $elapsed < $this->cutOffMarkTime) {
$callback();
try {
$callback();
} catch (UserNotFoundException $e) {
// 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->debug('Skipping share mount update for unresolvable user ' . $user->getUID(), ['exception' => $e]);
}
} else {
$this->markUserForRefresh($user);
}

@ -19,6 +19,7 @@ use OCP\Share\Events\BeforeShareDeletedEvent;
use OCP\Share\Events\ShareCreatedEvent;
use OCP\Share\IManager;
use OCP\Share\IShare;
use OCP\User\Exceptions\UserNotFoundException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Clock\ClockInterface;
@ -117,6 +118,33 @@ class SharesUpdatedListenerTest extends \Test\TestCase {
$this->sharesUpdatedListener->handle($event);
}
public function testShareAddedSkipsUnresolvableUser(): void {
$share = $this->createMock(IShare::class);
$user1 = $this->createUser('user1', '');
$user2 = $this->createUser('user2', '');
$this->manager->method('getUsersForShare')
->willReturn([$user1, $user2]);
$event = new ShareCreatedEvent($share);
// user1 is an orphaned recipient that no backend can resolve
$this->shareRecipientUpdater
->expects($this->exactly(2))
->method('updateForAddedShare')
->willReturnCallback(function (IUser $user) use ($user1): void {
if ($user === $user1) {
throw new UserNotFoundException('Backends provided no user object');
}
});
// the failure is logged, not thrown
$this->logger->expects($this->once())->method('debug');
// must not throw: user2 is still processed
$this->sharesUpdatedListener->handle($event);
}
public function testShareAccessUpdated() {
$user1 = $this->createUser('user1', '');
$user2 = $this->createUser('user2', '');

Loading…
Cancel
Save