-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Expand file tree
/
Copy pathFixOwncloudGroupSubshareStatus.php
More file actions
88 lines (75 loc) · 3.07 KB
/
Copy pathFixOwncloudGroupSubshareStatus.php
File metadata and controls
88 lines (75 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Sharing\Command;
use OC\Core\Command\Base;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\Share\IShare;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Fixes USERGROUP subshares that were created without `accepted = STATUS_ACCEPTED`
* by a rename on an ownCloud-migrated instance.
*
* When an OC-migrated group share (which has no per-user USERGROUP subshare) is
* renamed for the first time, DefaultShareProvider::move() inserted a new USERGROUP
* row without setting `accepted`. The column defaulted to 0 (STATUS_PENDING), causing
* MountProvider to skip the share on the next login — the file disappeared for the
* recipient.
*
* USERGROUP subshares with permissions = 0 were explicitly declined by the user
* and are left untouched.
*/
class FixOwncloudGroupSubshareStatus extends Base {
public function __construct(
private IDBConnection $connection,
) {
parent::__construct();
}
#[\Override]
protected function configure(): void {
$this
->setName('sharing:fix-owncloud-group-shares')
->setDescription('Fix group share subshares left pending after renaming on an ownCloud-migrated instance')
->addOption(
'dry-run',
null,
InputOption::VALUE_NONE,
'Show how many shares would be fixed without making any changes',
);
}
#[\Override]
public function execute(InputInterface $input, OutputInterface $output): int {
$dryRun = $input->getOption('dry-run');
$qb = $this->connection->getQueryBuilder();
$count = (int)$qb->select($qb->func()->count('id'))
->from('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
->executeQuery()
->fetchOne();
if ($count === 0) {
$output->writeln('No affected group share subshares found.');
return self::SUCCESS;
}
if ($dryRun) {
$output->writeln("Would fix <info>$count</info> group share subshare(s) (dry-run, no changes made).");
return self::SUCCESS;
}
$qb = $this->connection->getQueryBuilder();
$qb->update('share')
->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED, IQueryBuilder::PARAM_INT))
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
->executeStatement();
$output->writeln("Fixed <info>$count</info> group share subshare(s).");
return self::SUCCESS;
}
}