fix: handle circle shares in share target repair

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2026-02-10 22:28:37 +01:00 committed by backportbot[bot]
parent 4800b11a55
commit 3cb4b2faaf

View file

@ -14,7 +14,9 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountManager;
use OCP\Files\NotFoundException;
use OCP\ICacheFactory;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
@ -43,6 +45,7 @@ class CleanupShareTarget implements IRepairStep {
private readonly IMountManager $mountManager,
private readonly IRootFolder $rootFolder,
private readonly LoggerInterface $logger,
private readonly ICacheFactory $cacheFactory,
) {
}
@ -64,7 +67,14 @@ class CleanupShareTarget implements IRepairStep {
$userFolder = null;
foreach ($this->getProblemShares() as $shareInfo) {
$recipient = $this->userManager->getExistingUser($shareInfo['share_with']);
if ($shareInfo['share_type'] === IShare::TYPE_CIRCLE) {
$recipient = $this->getCircleShareOwner($shareInfo['share_with']);
if ($recipient === null) {
continue;
}
} else {
$recipient = $this->userManager->getExistingUser($shareInfo['share_with']);
}
if (!$recipient->isEnabled()) {
continue;
}
@ -112,6 +122,7 @@ class CleanupShareTarget implements IRepairStep {
$output->advance();
}
$this->cacheFactory->createDistributed('circles/')->clear();
$output->finishProgress();
$output->info("Fixed $count shares");
}
@ -143,7 +154,14 @@ class CleanupShareTarget implements IRepairStep {
$query->select('id', 'share_type', 'share_with', 'file_source', 'file_target')
->from('share')
->where($query->expr()->like('file_target', $query->createNamedParameter('% (_) (_)%')))
->andWhere($query->expr()->in('share_type', $query->createNamedParameter(self::USER_SHARE_TYPES, IQueryBuilder::PARAM_INT_ARRAY), IQueryBuilder::PARAM_INT_ARRAY))
->andWhere($query->expr()->orX(
$query->expr()->in('share_type', $query->createNamedParameter(self::USER_SHARE_TYPES, IQueryBuilder::PARAM_INT_ARRAY), IQueryBuilder::PARAM_INT_ARRAY),
$query->expr()->andX(
$query->expr()->eq('share_type', $query->createNamedParameter(
IShare::TYPE_CIRCLE, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT),
$query->expr()->isNotNull('parent'),
),
))
->orderBy('share_with')
->addOrderBy('id');
$result = $query->executeQuery();
@ -155,4 +173,25 @@ class CleanupShareTarget implements IRepairStep {
private function cleanTarget(string $target): string {
return preg_replace('/( \([2-9]\)){2,}/', '', $target);
}
/**
* Get the user of a federated user from circles, if the circle id belong to a user
*/
private function getCircleShareOwner(string $circleId): ?IUser {
$query = $this->connection->getQueryBuilder();
$query->select('name')
->from('circles_circle')
->where($query->expr()->eq('unique_id', $query->createNamedParameter($circleId)))
->andWhere($query->expr()->eq('source', $query->createNamedParameter(1, IQueryBuilder::PARAM_INT)));
$name = $query->executeQuery()->fetchOne();
if ($name === false) {
return null;
}
[$type, $userId,] = explode(':', $name, 3);
if ($type === 'user') {
return $this->userManager->getExistingUser($userId);
} else {
return null;
}
}
}