Skip to content

Commit

Permalink
chore(files_versions): Use new metadata API for versions
Browse files Browse the repository at this point in the history
As of: nextcloud/server#44049
Server equivalent: nextcloud/server#44175

Signed-off-by: Louis Chemineau <louis@chmn.me>
  • Loading branch information
artonge committed Mar 13, 2024
1 parent a3a6705 commit 2a8062a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 37 deletions.
4 changes: 2 additions & 2 deletions lib/Versions/GroupVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ public function __construct(
FileInfo $sourceFileInfo,
IVersionBackend $backend,
IUser $user,
string $label,
array $metadata,
private File $versionFile,
private int $folderId,
) {
parent::__construct($timestamp, $revisionId, $name, $size, $mimetype, $path, $sourceFileInfo, $backend, $user, $label);
parent::__construct($timestamp, $revisionId, $name, $size, $mimetype, $path, $sourceFileInfo, $backend, $user, $metadata);
}

public function getVersionFile(): File {
Expand Down
30 changes: 20 additions & 10 deletions lib/Versions/GroupVersionEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,33 @@ public function jsonSerialize(): array {
];
}

public function getLabel(): string {
return $this->getDecodedMetadata()['label'] ?? '';
public function getDecodedMetadata(): array {
return json_decode($this->metadata ?? '', true, 512, JSON_THROW_ON_ERROR) ?? [];
}

public function setLabel(string $label): void {
$metadata = $this->getDecodedMetadata();
$metadata['label'] = $label;
$this->setDecodedMetadata($metadata);
public function setDecodedMetadata(array $value): void {
$this->metadata = json_encode($value, JSON_THROW_ON_ERROR);
$this->markFieldUpdated('metadata');
}

public function getDecodedMetadata(): array {
return json_decode($this->metadata ?? '', true, 512, JSON_THROW_ON_ERROR) ?? [];
/**
* @abstract given a key, return the value associated with the key in the metadata column
* if nothing is found, we return an empty string
* @param string $key key associated with the value
*/
public function getMetadataValue(string $key): ?string {
return $this->getDecodedMetadata()[$key] ?? null;
}

public function setDecodedMetadata(array $value): void {
$this->metadata = json_encode($value, JSON_THROW_ON_ERROR);
/**
* @abstract sets a key value pair in the metadata column
* @param string $key key associated with the value
* @param string $value value associated with the key
*/
public function setMetadataValue(string $key, string $value): void {
$metadata = $this->getDecodedMetadata();
$metadata[$key] = $value;
$this->setDecodedMetadata($metadata);
$this->markFieldUpdated('metadata');
}
}
67 changes: 44 additions & 23 deletions lib/Versions/VersionsBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
namespace OCA\GroupFolders\Versions;

use OCA\Files_Versions\Versions\IDeletableVersionBackend;
use OCA\Files_Versions\Versions\INameableVersionBackend;
use OCA\Files_Versions\Versions\INeedSyncVersionBackend;
use OCA\Files_Versions\Versions\IVersion;
use OCA\Files_Versions\Versions\IVersionBackend;
Expand All @@ -41,9 +40,10 @@
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\IUserSession;
use Psr\Log\LoggerInterface;

class VersionsBackend implements IVersionBackend, INameableVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend {
class VersionsBackend implements IVersionBackend, IMetadataVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend {
public function __construct(
private IRootFolder $rootFolder,
private Folder $appFolder,
Expand All @@ -52,6 +52,7 @@ public function __construct(
private LoggerInterface $logger,
private GroupVersionsMapper $groupVersionsMapper,
private IMimeTypeLoader $mimeTypeLoader,
private IUserSession $userSession,
) {
}

Expand Down Expand Up @@ -165,7 +166,7 @@ function (GroupVersionEntity $versionEntity) use ($versionsFolder, $mountPoint,
$fileInfo,
$this,
$user,
$versionEntity->getLabel(),
$versionEntity->getMetadata(),
$versionFile,
$folderId,
);
Expand Down Expand Up @@ -206,21 +207,27 @@ public function createVersion(IUser $user, FileInfo $file) {
}

public function rollback(IVersion $version): void {
if ($version instanceof GroupVersion) {
$this->createVersion($version->getUser(), $version->getSourceFile());
if (!($version instanceof GroupVersion)) {
throw new \LogicException('Trying to restore a version from a file not in a group folder');
}

/** @var GroupMountPoint $targetMount */
$targetMount = $version->getSourceFile()->getMountPoint();
$targetCache = $targetMount->getStorage()->getCache();
$versionMount = $version->getVersionFile()->getMountPoint();
$versionCache = $versionMount->getStorage()->getCache();
if (!$this->currentUserHasPermissions($version->getSourceFile(), \OCP\Constants::PERMISSION_UPDATE)) {
throw new Forbidden('You cannot restore this version because you do not have update permissions on the source file.');
}

$targetInternalPath = $version->getSourceFile()->getInternalPath();
$versionInternalPath = $version->getVersionFile()->getInternalPath();
$this->createVersion($version->getUser(), $version->getSourceFile());

$targetMount->getStorage()->copyFromStorage($versionMount->getStorage(), $versionInternalPath, $targetInternalPath);
$versionMount->getStorage()->getCache()->copyFromCache($targetCache, $versionCache->get($versionInternalPath), $targetMount->getSourcePath() . '/' . $targetInternalPath);
}
/** @var GroupMountPoint $targetMount */
$targetMount = $version->getSourceFile()->getMountPoint();
$targetCache = $targetMount->getStorage()->getCache();
$versionMount = $version->getVersionFile()->getMountPoint();
$versionCache = $versionMount->getStorage()->getCache();

$targetInternalPath = $version->getSourceFile()->getInternalPath();
$versionInternalPath = $version->getVersionFile()->getInternalPath();

$targetMount->getStorage()->copyFromStorage($versionMount->getStorage(), $versionInternalPath, $targetInternalPath);
$versionMount->getStorage()->getCache()->copyFromCache($targetCache, $versionCache->get($versionInternalPath), $targetMount->getSourcePath() . '/' . $targetInternalPath);
}

public function read(IVersion $version) {
Expand All @@ -236,6 +243,7 @@ public function getVersionFile(IUser $user, FileInfo $sourceFile, $revision): Fi
if (!($mount instanceof GroupMountPoint)) {
throw new \LogicException('Trying to getVersionFile from a file not in a mounted group folder');
}

try {
/** @var Folder $versionsFolder */
$versionsFolder = $this->getVersionsFolder($mount->getFolderId())->get((string)$sourceFile->getId());
Expand Down Expand Up @@ -297,19 +305,22 @@ private function getVersionsFolder(int $folderId): Folder {
}
}

public function setVersionLabel(IVersion $version, string $label): void {
$versionEntity = $this->groupVersionsMapper->findVersionForFileId(
$version->getSourceFile()->getId(),
$version->getTimestamp(),
);
if (trim($label) === '') {
$label = null;
public function setMetadataValue(Node $node, int $revision, string $key, string $value): void {
if (!$this->currentUserHasPermissions($node, \OCP\Constants::PERMISSION_UPDATE)) {
throw new Forbidden('You cannot label this version because you do not have update permissions on the source file.');
}
$versionEntity->setLabel($label ?? '');

$versionEntity = $this->groupVersionsMapper->findVersionForFileId($node->getId(), $revision);

$versionEntity->setMetadataValue($key, $value);
$this->groupVersionsMapper->update($versionEntity);
}

public function deleteVersion(IVersion $version): void {
if (!$this->currentUserHasPermissions($version->getSourceFile(), \OCP\Constants::PERMISSION_DELETE)) {
throw new Forbidden('You cannot delete this version because you do not have delete permissions on the source file.');
}

$sourceFile = $version->getSourceFile();
$mount = $sourceFile->getMountPoint();

Expand Down Expand Up @@ -359,4 +370,14 @@ public function updateVersionEntity(File $sourceFile, int $revision, array $prop
public function deleteVersionsEntity(File $file): void {
$this->groupVersionsMapper->deleteAllVersionsForFileId($file->getId());
}

private function currentUserHasPermissions(FileInfo $sourceFile, int $permissions): bool {
$currentUserId = $this->userSession->getUser()?->getUID();

if ($currentUserId === null) {
throw new NotFoundException("No user logged in");
}

return ($sourceFile->getPermissions() & $permissions) === $permissions;
}
}
4 changes: 2 additions & 2 deletions tests/stub.phpstub
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ namespace OCA\Files_Versions\Versions {
public function getVersionFile(\OCP\IUser $user, \OCP\Files\FileInfo $sourceFile, $revision) : \OCP\Files\File;
}

interface INameableVersionBackend {
public function setVersionLabel(IVersion $version, string $label): void;
interface IMetadataVersionBackend {
public function setMetadataValue(Node $node, int $revision, string $key, string $value): void;
}

interface IDeletableVersionBackend {
Expand Down

0 comments on commit 2a8062a

Please sign in to comment.