diff options
Diffstat (limited to 'apps/files_versions/lib/Versions/LegacyVersionsBackend.php')
-rw-r--r-- | apps/files_versions/lib/Versions/LegacyVersionsBackend.php | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php index 1483d03bcc6..48d69d31629 100644 --- a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php +++ b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php @@ -12,11 +12,10 @@ namespace OCA\Files_Versions\Versions; use Exception; use OC\Files\View; use OCA\DAV\Connector\Sabre\Exception\Forbidden; -use OCA\Files_Sharing\ISharedStorage; -use OCA\Files_Sharing\SharedStorage; use OCA\Files_Versions\Db\VersionEntity; use OCA\Files_Versions\Db\VersionsMapper; use OCA\Files_Versions\Storage; +use OCP\Constants; use OCP\Files\File; use OCP\Files\FileInfo; use OCP\Files\Folder; @@ -24,6 +23,7 @@ use OCP\Files\IMimeTypeLoader; use OCP\Files\IRootFolder; use OCP\Files\Node; use OCP\Files\NotFoundException; +use OCP\Files\Storage\ISharedStorage; use OCP\Files\Storage\IStorage; use OCP\IUser; use OCP\IUserManager; @@ -48,8 +48,12 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend public function getVersionsForFile(IUser $user, FileInfo $file): array { $storage = $file->getStorage(); - if ($storage->instanceOfStorage(SharedStorage::class)) { + if ($storage->instanceOfStorage(ISharedStorage::class)) { $owner = $storage->getOwner(''); + if ($owner === false) { + throw new NotFoundException('No owner for ' . $file->getPath()); + } + $user = $this->userManager->get($owner); $fileId = $file->getId(); @@ -66,7 +70,7 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend $file = $userFolder->getFirstNodeById($fileId); if (!$file) { - throw new NotFoundException("version file not found for share owner"); + throw new NotFoundException('version file not found for share owner'); } } else { $userFolder = $this->rootFolder->getUserFolder($user->getUID()); @@ -159,7 +163,7 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend } public function rollback(IVersion $version) { - if (!$this->currentUserHasPermissions($version->getSourceFile(), \OCP\Constants::PERMISSION_UPDATE)) { + if (!$this->currentUserHasPermissions($version->getSourceFile(), Constants::PERMISSION_UPDATE)) { throw new Forbidden('You cannot restore this version because you do not have update permissions on the source file.'); } @@ -192,7 +196,7 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend // Shared files have their versions in the owners root folder so we need to obtain them from there if ($storage->instanceOfStorage(ISharedStorage::class) && $owner) { - /** @var SharedStorage $storage */ + /** @var ISharedStorage $storage */ $userFolder = $this->rootFolder->getUserFolder($owner->getUID()); $user = $owner; $ownerPathInStorage = $sourceFile->getInternalPath(); @@ -208,8 +212,12 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend return $file; } + public function getRevision(Node $node): int { + return $node->getMTime(); + } + public function deleteVersion(IVersion $version): void { - if (!$this->currentUserHasPermissions($version->getSourceFile(), \OCP\Constants::PERMISSION_DELETE)) { + if (!$this->currentUserHasPermissions($version->getSourceFile(), Constants::PERMISSION_DELETE)) { throw new Forbidden('You cannot delete this version because you do not have delete permissions on the source file.'); } @@ -221,14 +229,35 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend $this->versionsMapper->delete($versionEntity); } - public function createVersionEntity(File $file): void { + public function createVersionEntity(File $file): ?VersionEntity { $versionEntity = new VersionEntity(); $versionEntity->setFileId($file->getId()); $versionEntity->setTimestamp($file->getMTime()); $versionEntity->setSize($file->getSize()); $versionEntity->setMimetype($this->mimeTypeLoader->getId($file->getMimetype())); $versionEntity->setMetadata([]); - $this->versionsMapper->insert($versionEntity); + + $tries = 1; + while ($tries < 5) { + try { + $this->versionsMapper->insert($versionEntity); + return $versionEntity; + } catch (\OCP\DB\Exception $e) { + if (!in_array($e->getReason(), [ + \OCP\DB\Exception::REASON_CONSTRAINT_VIOLATION, + \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION, + ]) + ) { + throw $e; + } + /* Conflict with another version, increase mtime and try again */ + $versionEntity->setTimestamp($versionEntity->getTimestamp() + 1); + $tries++; + $this->logger->warning('Constraint violation while inserting version, retrying with increased timestamp', ['exception' => $e]); + } + } + + return null; } public function updateVersionEntity(File $sourceFile, int $revision, array $properties): void { @@ -257,7 +286,7 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend $currentUserId = $this->userSession->getUser()?->getUID(); if ($currentUserId === null) { - throw new NotFoundException("No user logged in"); + throw new NotFoundException('No user logged in'); } if ($sourceFile->getOwner()?->getUID() === $currentUserId) { @@ -267,7 +296,7 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend $nodes = $this->rootFolder->getUserFolder($currentUserId)->getById($sourceFile->getId()); if (count($nodes) === 0) { - throw new NotFoundException("Version file not accessible by current user"); + throw new NotFoundException('Version file not accessible by current user'); } foreach ($nodes as $node) { @@ -280,7 +309,7 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend } public function setMetadataValue(Node $node, int $revision, string $key, string $value): void { - if (!$this->currentUserHasPermissions($node, \OCP\Constants::PERMISSION_UPDATE)) { + if (!$this->currentUserHasPermissions($node, Constants::PERMISSION_UPDATE)) { throw new Forbidden('You cannot update the version\'s metadata because you do not have update permissions on the source file.'); } @@ -343,16 +372,20 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend * @inheritdoc */ public function clearVersionsForFile(IUser $user, Node $source, Node $target): void { - $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $userId = $user->getUID(); + $userFolder = $this->rootFolder->getUserFolder($userId); $relativePath = $userFolder->getRelativePath($source->getPath()); if ($relativePath === null) { - throw new Exception("Relative path not found for node with path: " . $source->getPath()); + throw new Exception('Relative path not found for node with path: ' . $source->getPath()); + } + + $versionFolder = $this->rootFolder->get($userId . '/files_versions'); + if (!$versionFolder instanceof Folder) { + throw new Exception('User versions folder does not exist'); } - $versions = Storage::getVersions($user->getUID(), $relativePath); - /** @var Folder versionFolder */ - $versionFolder = $this->rootFolder->get('admin/files_versions'); + $versions = Storage::getVersions($userId, $relativePath); foreach ($versions as $version) { $versionFolder->get($version['path'] . '.v' . (int)$version['version'])->delete(); } |