Skip to content

Commit 5b01338

Browse files
fix(sharing): add command to fix broken shares after ownership transferring
Signed-off-by: Luka Trovic <luka@nextcloud.com>
1 parent 6fa4266 commit 5b01338

5 files changed

Lines changed: 92 additions & 0 deletions

File tree

apps/files_sharing/appinfo/info.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Turning the feature off removes shared files and folders on the server for all s
4949
<command>OCA\Files_Sharing\Command\CleanupRemoteStorages</command>
5050
<command>OCA\Files_Sharing\Command\ExiprationNotification</command>
5151
<command>OCA\Files_Sharing\Command\DeleteOrphanShares</command>
52+
<command>OCA\Files_Sharing\Command\FixBrokenShares</command>
5253
</commands>
5354

5455
<settings>

apps/files_sharing/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
'OCA\\Files_Sharing\\Command\\CleanupRemoteStorages' => $baseDir . '/../lib/Command/CleanupRemoteStorages.php',
2828
'OCA\\Files_Sharing\\Command\\DeleteOrphanShares' => $baseDir . '/../lib/Command/DeleteOrphanShares.php',
2929
'OCA\\Files_Sharing\\Command\\ExiprationNotification' => $baseDir . '/../lib/Command/ExiprationNotification.php',
30+
'OCA\\Files_Sharing\\Command\\FixBrokenShares' => $baseDir . '/../lib/Command/FixBrokenShares.php',
3031
'OCA\\Files_Sharing\\Controller\\AcceptController' => $baseDir . '/../lib/Controller/AcceptController.php',
3132
'OCA\\Files_Sharing\\Controller\\DeletedShareAPIController' => $baseDir . '/../lib/Controller/DeletedShareAPIController.php',
3233
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => $baseDir . '/../lib/Controller/ExternalSharesController.php',

apps/files_sharing/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class ComposerStaticInitFiles_Sharing
4242
'OCA\\Files_Sharing\\Command\\CleanupRemoteStorages' => __DIR__ . '/..' . '/../lib/Command/CleanupRemoteStorages.php',
4343
'OCA\\Files_Sharing\\Command\\DeleteOrphanShares' => __DIR__ . '/..' . '/../lib/Command/DeleteOrphanShares.php',
4444
'OCA\\Files_Sharing\\Command\\ExiprationNotification' => __DIR__ . '/..' . '/../lib/Command/ExiprationNotification.php',
45+
'OCA\\Files_Sharing\\Command\\FixBrokenShares' => __DIR__ . '/..' . '/../lib/Command/FixBrokenShares.php',
4546
'OCA\\Files_Sharing\\Controller\\AcceptController' => __DIR__ . '/..' . '/../lib/Controller/AcceptController.php',
4647
'OCA\\Files_Sharing\\Controller\\DeletedShareAPIController' => __DIR__ . '/..' . '/../lib/Controller/DeletedShareAPIController.php',
4748
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => __DIR__ . '/..' . '/../lib/Controller/ExternalSharesController.php',
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace OCA\Files_Sharing\Command;
10+
11+
use OC\Core\Command\Base;
12+
use OCA\Files_Sharing\OrphanHelper;
13+
use Symfony\Component\Console\Input\InputInterface;
14+
use Symfony\Component\Console\Input\InputOption;
15+
use Symfony\Component\Console\Output\OutputInterface;
16+
17+
class FixBrokenShares extends Base {
18+
public function __construct(
19+
private readonly OrphanHelper $orphanHelper
20+
) {
21+
parent::__construct();
22+
}
23+
24+
protected function configure(): void {
25+
$this
26+
->setName('sharing:fix-broken-shares')
27+
->setDescription('Fix broken shares after transfer ownership on old versions')
28+
->addOption(
29+
'dry-run',
30+
null,
31+
InputOption::VALUE_NONE,
32+
'only show which shares would be updated'
33+
);
34+
}
35+
36+
public function execute(InputInterface $input, OutputInterface $output): int {
37+
$shares = $this->orphanHelper->getAllShares();
38+
$dryRun = $input->getOption('dry-run');
39+
$count = 0;
40+
41+
foreach ($shares as $share) {
42+
if ($this->orphanHelper->isShareValid($share['owner'], $share['fileid']) || !$this->orphanHelper->fileExists($share['fileid'])) {
43+
continue;
44+
}
45+
46+
$owner = $this->orphanHelper->findOwner($share['fileid']);
47+
48+
if ($owner !== null) {
49+
if ($dryRun) {
50+
$output->writeln("Share with id <info>{$share['id']}</info> (target: <info>{$share['target']}</info>) can be updated to owner <info>$owner</info>");
51+
} else {
52+
$this->orphanHelper->updateShareOwner($share['id'], $owner);
53+
$output->writeln("Share with id <info>{$share['id']}</info> (target: <info>{$share['target']}</info>) updated to owner <info>$owner</info>");
54+
}
55+
$count++;
56+
}
57+
}
58+
59+
if ($count === 0) {
60+
$output->writeln('No broken shares detected');
61+
}
62+
63+
return static::SUCCESS;
64+
}
65+
}

apps/files_sharing/lib/OrphanHelper.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010

1111
use OC\User\NoUserException;
1212
use OCP\DB\QueryBuilder\IQueryBuilder;
13+
use OCP\Files\Config\IUserMountCache;
1314
use OCP\Files\IRootFolder;
1415
use OCP\IDBConnection;
1516

1617
class OrphanHelper {
1718
public function __construct(
1819
private IDBConnection $connection,
1920
private IRootFolder $rootFolder,
21+
private IUserMountCache $userMountCache,
2022
) {
2123
}
2224

@@ -68,4 +70,26 @@ public function getAllShares() {
6870
];
6971
}
7072
}
73+
74+
public function findOwner(int $fileId): ?string {
75+
$mounts = $this->userMountCache->getMountsForFileId($fileId);
76+
if (!$mounts) {
77+
return null;
78+
}
79+
foreach ($mounts as $mount) {
80+
// Only the mount of owner has the internal path value
81+
if ($mount->getInternalPath()) {
82+
return $mount->getUser()->getUID();
83+
}
84+
}
85+
return null;
86+
}
87+
88+
public function updateShareOwner(int $shareId, string $owner): void {
89+
$query = $this->connection->getQueryBuilder();
90+
$query->update('share')
91+
->set('uid_owner', $query->createNamedParameter($owner))
92+
->where($query->expr()->eq('id', $query->createNamedParameter($shareId, IQueryBuilder::PARAM_INT)));
93+
$query->executeStatement();
94+
}
7195
}

0 commit comments

Comments
 (0)