Skip to content

Commit 9ee4fa8

Browse files
authored
Merge pull request #62925 from nextcloud/leftybournes/fix/trashbin_show_deletedby
fix(trashbin): properly show deleted by for federated shares
2 parents 630cd75 + d7b0c3d commit 9ee4fa8

4 files changed

Lines changed: 60 additions & 1 deletion

File tree

apps/files_trashbin/lib/Trash/LegacyTrashBackend.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use OCA\Files_Trashbin\Helper;
1313
use OCA\Files_Trashbin\Storage;
1414
use OCA\Files_Trashbin\Trashbin;
15+
use OCP\Federation\ICloudIdManager;
1516
use OCP\Files\FileInfo;
1617
use OCP\Files\Folder;
1718
use OCP\Files\IRootFolder;
@@ -28,6 +29,7 @@ class LegacyTrashBackend implements ITrashBackend {
2829
public function __construct(
2930
private readonly IRootFolder $rootFolder,
3031
private readonly IUserManager $userManager,
32+
private readonly ICloudIdManager $cloudIdManager,
3133
) {
3234
}
3335

@@ -40,7 +42,7 @@ private function mapTrashItem(FileInfo $file, IUser $user, ?ITrashItem $parent =
4042
$originalLocation = $file->getName();
4143
}
4244
/** @psalm-suppress UndefinedInterfaceMethod */
43-
$deletedBy = $this->userManager->get($file['deletedBy']) ?? $parent?->getDeletedBy();
45+
$deletedBy = $this->resolveDeletedBy($file['deletedBy']) ?? $parent?->getDeletedBy();
4446
$trashFilename = Trashbin::getTrashFilename($file->getName(), $file->getMtime());
4547
return new TrashItem(
4648
$this,
@@ -127,4 +129,29 @@ public function getTrashNodeById(IUser $user, int $fileId): ?Node {
127129
return null;
128130
}
129131
}
132+
133+
/**
134+
* Resolve the user that deleted a trash item. Files deleted by a federated share
135+
* recipient only carry the recipient's remote cloud ID, which no local IUserManager
136+
* backend can resolve, so fall back to a display-only user for the cloud ID in that
137+
* case instead of leaving the item without an "Unknown" deleted by user.
138+
*/
139+
private function resolveDeletedBy(?string $uid): ?IUser {
140+
if (!$uid) {
141+
return null;
142+
}
143+
144+
$user = $this->userManager->get($uid);
145+
if ($user !== null) {
146+
return $user;
147+
}
148+
149+
try {
150+
$cloudId = $this->cloudIdManager->resolveCloudId($uid);
151+
} catch (\InvalidArgumentException $e) {
152+
return null;
153+
}
154+
155+
return $this->userManager->getFederatedUser($cloudId);
156+
}
130157
}

lib/private/User/Manager.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OCP\Config\IUserConfig;
1414
use OCP\DB\QueryBuilder\IQueryBuilder;
1515
use OCP\EventDispatcher\IEventDispatcher;
16+
use OCP\Federation\ICloudId;
1617
use OCP\HintException;
1718
use OCP\ICache;
1819
use OCP\ICacheFactory;
@@ -883,4 +884,9 @@ public function getAvatarUrlLight(string $userId, int $size): string {
883884
public function getAvatarUrlDark(string $userId, int $size): string {
884885
return ($this->urlGenerator ??= Server::get(IURLGenerator::class))->linkToRouteAbsolute('core.avatar.getAvatarDark', ['userId' => $userId, 'size' => $size]);
885886
}
887+
888+
#[\Override]
889+
public function getFederatedUser(ICloudId $cloudId): IUser {
890+
return new LazyUser($cloudId->getDisplayId(), $this, $cloudId->getDisplayId());
891+
}
886892
}

lib/public/IUserManager.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,15 @@ public function getAvatarUrlLight(string $userId, int $size): string;
282282
* @since 34.0.0
283283
*/
284284
public function getAvatarUrlDark(string $userId, int $size): string;
285+
286+
/**
287+
* Get a read-only user from a cloud ID for showing the display name of a remote
288+
* federation user (e.g. the "deleted by" user of a federated share) that has no
289+
* local account.
290+
*
291+
* @param \OCP\Federation\ICloudId $federatedUserId A cloud ID of the federated user
292+
* @return IUser
293+
* @since 35.0.0
294+
*/
295+
public function getFederatedUser(\OCP\Federation\ICloudId $cloudId): IUser;
285296
}

tests/lib/User/ManagerTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use OC\User\User;
1616
use OCP\Config\IUserConfig;
1717
use OCP\EventDispatcher\IEventDispatcher;
18+
use OCP\Federation\ICloudId;
1819
use OCP\ICache;
1920
use OCP\ICacheFactory;
2021
use OCP\IConfig;
@@ -736,4 +737,18 @@ public function testGetAvatarUrlLight(): void {
736737
public function testGetAvatarUrlDark(): void {
737738
$this->assertEquals('http://localhost/index.php/avatar/userid/64/dark', $this->manager->getAvatarUrlDark('userid', 64));
738739
}
740+
741+
public function testGetFederatedUser(): void {
742+
$userId = 'test@example.com';
743+
744+
$cloudId = $this->createMock(ICloudId::class);
745+
$cloudId->expects($this->exactly(2))
746+
->method('getDisplayId')
747+
->willReturn($userId);
748+
749+
$user = $this->manager->getFederatedUser($cloudId);
750+
751+
$this->assertEquals($userId, $user->getUID());
752+
$this->assertEquals($userId, $user->getDisplayName());
753+
}
739754
}

0 commit comments

Comments
 (0)