Browse Source

Merge pull request #44049 from nextcloud/feat/show-name-of-user-in-versions

feat: show the id of last author in versions metadata
tags/v29.0.0beta2
Eduardo Morales 3 months ago
parent
commit
f99b820cd0
No account linked to committer's email address

+ 3
- 0
apps/files_versions/composer/composer/autoload_classmap.php View File

@@ -21,6 +21,7 @@ return array(
'OCA\\Files_Versions\\Listener\\FileEventsListener' => $baseDir . '/../lib/Listener/FileEventsListener.php',
'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
'OCA\\Files_Versions\\Listener\\MetadataFileEvents' => $baseDir . '/../lib/Listener/MetadataFileEvents.php',
'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => $baseDir . '/../lib/Migration/Version1020Date20221114144058.php',
'OCA\\Files_Versions\\Sabre\\Plugin' => $baseDir . '/../lib/Sabre/Plugin.php',
'OCA\\Files_Versions\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php',
@@ -32,6 +33,8 @@ return array(
'OCA\\Files_Versions\\Storage' => $baseDir . '/../lib/Storage.php',
'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => $baseDir . '/../lib/Versions/BackendNotFoundException.php',
'OCA\\Files_Versions\\Versions\\IDeletableVersionBackend' => $baseDir . '/../lib/Versions/IDeletableVersionBackend.php',
'OCA\\Files_Versions\\Versions\\IMetadataVersion' => $baseDir . '/../lib/Versions/IMetadataVersion.php',
'OCA\\Files_Versions\\Versions\\IMetadataVersionBackend' => $baseDir . '/../lib/Versions/IMetadataVersionBackend.php',
'OCA\\Files_Versions\\Versions\\INameableVersion' => $baseDir . '/../lib/Versions/INameableVersion.php',
'OCA\\Files_Versions\\Versions\\INameableVersionBackend' => $baseDir . '/../lib/Versions/INameableVersionBackend.php',
'OCA\\Files_Versions\\Versions\\INeedSyncVersionBackend' => $baseDir . '/../lib/Versions/INeedSyncVersionBackend.php',

+ 3
- 0
apps/files_versions/composer/composer/autoload_static.php View File

@@ -36,6 +36,7 @@ class ComposerStaticInitFiles_Versions
'OCA\\Files_Versions\\Listener\\FileEventsListener' => __DIR__ . '/..' . '/../lib/Listener/FileEventsListener.php',
'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
'OCA\\Files_Versions\\Listener\\MetadataFileEvents' => __DIR__ . '/..' . '/../lib/Listener/MetadataFileEvents.php',
'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => __DIR__ . '/..' . '/../lib/Migration/Version1020Date20221114144058.php',
'OCA\\Files_Versions\\Sabre\\Plugin' => __DIR__ . '/..' . '/../lib/Sabre/Plugin.php',
'OCA\\Files_Versions\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php',
@@ -47,6 +48,8 @@ class ComposerStaticInitFiles_Versions
'OCA\\Files_Versions\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php',
'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => __DIR__ . '/..' . '/../lib/Versions/BackendNotFoundException.php',
'OCA\\Files_Versions\\Versions\\IDeletableVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IDeletableVersionBackend.php',
'OCA\\Files_Versions\\Versions\\IMetadataVersion' => __DIR__ . '/..' . '/../lib/Versions/IMetadataVersion.php',
'OCA\\Files_Versions\\Versions\\IMetadataVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IMetadataVersionBackend.php',
'OCA\\Files_Versions\\Versions\\INameableVersion' => __DIR__ . '/..' . '/../lib/Versions/INameableVersion.php',
'OCA\\Files_Versions\\Versions\\INameableVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/INameableVersionBackend.php',
'OCA\\Files_Versions\\Versions\\INeedSyncVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/INeedSyncVersionBackend.php',

+ 2
- 2
apps/files_versions/composer/composer/installed.php View File

@@ -3,7 +3,7 @@
'name' => '__root__',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'a820e3d036741ad1194361eca11bc1cbcdda0a47',
'reference' => '84930a207a8d5f0ef32320796fe188892b63fa19',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
@@ -13,7 +13,7 @@
'__root__' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'a820e3d036741ad1194361eca11bc1cbcdda0a47',
'reference' => '84930a207a8d5f0ef32320796fe188892b63fa19',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),

+ 3
- 0
apps/files_versions/lib/AppInfo/Application.php View File

@@ -36,6 +36,7 @@ use OCA\Files_Versions\Capabilities;
use OCA\Files_Versions\Listener\FileEventsListener;
use OCA\Files_Versions\Listener\LoadAdditionalListener;
use OCA\Files_Versions\Listener\LoadSidebarListener;
use OCA\Files_Versions\Listener\MetadataFileEvents;
use OCA\Files_Versions\Versions\IVersionManager;
use OCA\Files_Versions\Versions\VersionManager;
use OCP\Accounts\IAccountManager;
@@ -119,6 +120,8 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(NodeCopiedEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeRenamedEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeCopiedEvent::class, FileEventsListener::class);
$context->registerEventListener(NodeWrittenEvent::class, MetadataFileEvents::class);
}

public function boot(IBootContext $context): void {

+ 19
- 0
apps/files_versions/lib/Db/VersionEntity.php View File

@@ -78,4 +78,23 @@ class VersionEntity extends Entity implements JsonSerializable {
$this->metadata['label'] = $label;
$this->markFieldUpdated('metadata');
}

/**
* @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->metadata[$key] ?? null;
}

/**
* @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 {
$this->metadata[$key] = $value;
$this->markFieldUpdated('metadata');
}
}

+ 1
- 1
apps/files_versions/lib/Db/VersionsMapper.php View File

@@ -85,7 +85,7 @@ class VersionsMapper extends QBMapper {
->executeStatement();
}

public function deleteAllVersionsForUser(int $storageId, string $path = null): void {
public function deleteAllVersionsForUser(int $storageId, ?string $path = null): void {
$fileIdsGenerator = $this->getFileIdsGenerator($storageId, $path);

$versionEntitiesDeleteQuery = $this->db->getQueryBuilder();

+ 68
- 0
apps/files_versions/lib/Listener/MetadataFileEvents.php View File

@@ -0,0 +1,68 @@
<?php

declare(strict_types=1);

/**
* @author Eduardo Morales emoral435@gmail.com>
*
* @license GNU AGPL-3.0-or-later
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files_Versions\Listener;

use OC\Files\Node\Folder;
use OCA\Files_Versions\Versions\IMetadataVersionBackend;
use OCA\Files_Versions\Versions\IVersionManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Events\Node\NodeWrittenEvent;
use OCP\Files\Node;
use OCP\IUserSession;

/** @template-implements IEventListener<NodeWrittenEvent> */
class MetadataFileEvents implements IEventListener {
public function __construct(
private IVersionManager $versionManager,
private IUserSession $userSession,
) {
}

/**
* @abstract handles events from a nodes version being changed
* @param Event $event the event that triggered this listener to activate
*/
public function handle(Event $event): void {
if ($event instanceof NodeWrittenEvent) {
$this->post_write_hook($event->getNode());
}
}

/**
* @abstract handles the NodeWrittenEvent, and sets the metadata for the associated node
* @param Node $node the node that is currently being written
*/
public function post_write_hook(Node $node): void {
$user = $this->userSession->getUser();
// Do not handle folders or users that we cannot get metadata from
if ($node instanceof Folder || is_null($user)) {
return;
}
// check if our version manager supports setting the metadata
if ($this->versionManager instanceof IMetadataVersionBackend) {
$author = $user->getUID();
$this->versionManager->setMetadataValue($node, 'author', $author);
}
}
}

+ 3
- 0
apps/files_versions/lib/Sabre/Plugin.php View File

@@ -44,6 +44,8 @@ class Plugin extends ServerPlugin {

public const VERSION_LABEL = '{http://nextcloud.org/ns}version-label';

public const VERSION_AUTHOR = '{http://nextcloud.org/ns}version-author'; // dav property for author

public function __construct(
private IRequest $request,
private IPreview $previewManager,
@@ -93,6 +95,7 @@ class Plugin extends ServerPlugin {
public function propFind(PropFind $propFind, INode $node): void {
if ($node instanceof VersionFile) {
$propFind->handle(self::VERSION_LABEL, fn () => $node->getLabel());
$propFind->handle(self::VERSION_AUTHOR, fn () => $node->getMetadataValue("author"));
$propFind->handle(FilesPlugin::HAS_PREVIEW_PROPERTYNAME, fn () => $this->previewManager->isMimeSupported($node->getContentType()));
}
}

+ 8
- 0
apps/files_versions/lib/Sabre/VersionFile.php View File

@@ -27,6 +27,7 @@ declare(strict_types=1);
namespace OCA\Files_Versions\Sabre;

use OCA\Files_Versions\Versions\IDeletableVersionBackend;
use OCA\Files_Versions\Versions\IMetadataVersion;
use OCA\Files_Versions\Versions\INameableVersion;
use OCA\Files_Versions\Versions\INameableVersionBackend;
use OCA\Files_Versions\Versions\IVersion;
@@ -109,6 +110,13 @@ class VersionFile implements IFile {
}
}

public function getMetadataValue(string $key): ?string {
if ($this->version instanceof IMetadataVersion) {
return $this->version->getMetadataValue($key);
}
return null;
}

public function getLastModified(): int {
return $this->version->getTimestamp();
}

+ 38
- 0
apps/files_versions/lib/Versions/IMetadataVersion.php View File

@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2024 Eduardo Morales <emoral435@gmail.com>
*
* @license GNU AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Files_Versions\Versions;

/**
* This interface allows for just direct accessing of the metadata column JSON
* @since 29.0.0
*/
interface IMetadataVersion {
/**
* retrieves the metadata value from our $key param
*
* @param string $key the key for the json value of the metadata column
* @since 29.0.0
*/
public function getMetadataValue(string $key): ?string;
}

+ 52
- 0
apps/files_versions/lib/Versions/IMetadataVersionBackend.php View File

@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2024 Eduardo Morales <emoral435@gmail.com>
*
* @license GNU AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Files_Versions\Versions;

use OCP\Files\Node;

/**
* This interface edits the metadata column of a node.
* Each column of the metadata has a key => value mapping.
* @since 29.0.0
*/
interface IMetadataVersionBackend {
/**
* Sets a key value pair in the metadata column corresponding to the node's version.
*
* @param Node $node the node that triggered the Metadata event listener, aka, the file version
* @param string $key the key for the json value of the metadata column
* @param string $value the value that corresponds to the key in the metadata column
* @since 29.0.0
*/
public function setMetadataValue(Node $node, string $key, string $value): void;

/**
* Retrieves a corresponding value from the metadata column using the key.
*
* @param Node $node the node that triggered the Metadata event listener, aka, the file version
* @param string $key the key for the json value of the metadata column
* @since 29.0.0
*/
public function getMetadataValue(Node $node, string $key): ?string;
}

+ 2
- 1
apps/files_versions/lib/Versions/INameableVersion.php View File

@@ -24,12 +24,13 @@ declare(strict_types=1);
namespace OCA\Files_Versions\Versions;

/**
* @deprecated 29.0.0
* @since 26.0.0
*/
interface INameableVersion {
/**
* Get the user created label
*
* @deprecated 29.0.0
* @return string
* @since 26.0.0
*/

+ 2
- 1
apps/files_versions/lib/Versions/INameableVersionBackend.php View File

@@ -24,12 +24,13 @@ declare(strict_types=1);
namespace OCA\Files_Versions\Versions;

/**
* @deprecated 29.0.0
* @since 26.0.0
*/
interface INameableVersionBackend {
/**
* Set the label for a version.
*
* @deprecated 29.0.0
* @since 26.0.0
*/
public function setVersionLabel(IVersion $version, string $label): void;

+ 31
- 1
apps/files_versions/lib/Versions/LegacyVersionsBackend.php View File

@@ -39,13 +39,14 @@ use OCP\Files\FileInfo;
use OCP\Files\Folder;
use OCP\Files\IMimeTypeLoader;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;

class LegacyVersionsBackend implements IVersionBackend, INameableVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend {
class LegacyVersionsBackend implements IVersionBackend, INameableVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend, IMetadataVersionBackend {
private IRootFolder $rootFolder;
private IUserManager $userManager;
private VersionsMapper $versionsMapper;
@@ -312,4 +313,33 @@ class LegacyVersionsBackend implements IVersionBackend, INameableVersionBackend,

return ($sourceFile->getPermissions() & $permissions) === $permissions;
}

public function setMetadataValue(Node $node, string $key, string $value): void {
// Do not handle folders.
if ($node instanceof File) {

try {
$versionEntity = $this->versionsMapper->findVersionForFileId($node->getId(), $node->getMTime());
} catch (\Exception $e) {
throw $e; // the version does not exist or too many versions exist
}

$currentMetadata = $versionEntity->getMetadata() ?? [];
$currentMetadata[$key] = $value;
$versionEntity->setMetadata($currentMetadata);
$this->versionsMapper->update($versionEntity);
}

}

public function getMetadataValue(Node $node, string $key): ?string {
try {
$versionEntity = $this->versionsMapper->findVersionForFileId($node->getId(), $node->getMTime());
return $versionEntity->getMetadataValue($key);
} catch (\InvalidArgumentException $e) {
// we tried to find a version or key that doesn't exist
return null;
}
}
}

+ 9
- 1
apps/files_versions/lib/Versions/Version.php View File

@@ -26,9 +26,10 @@ declare(strict_types=1);
namespace OCA\Files_Versions\Versions;

use OCP\Files\FileInfo;
use OCP\Files\Node;
use OCP\IUser;

class Version implements IVersion, INameableVersion {
class Version implements IVersion, INameableVersion, IMetadataVersion {
/** @var int */
private $timestamp;

@@ -121,4 +122,11 @@ class Version implements IVersion, INameableVersion {
public function getUser(): IUser {
return $this->user;
}

public function getMetadataValue(string $key): ?string {
if ($this->backend instanceof IMetadataVersionBackend && $this->sourceFileInfo instanceof Node) {
return $this->backend->getMetadataValue($this->sourceFileInfo, "author");
}
return null;
}
}

+ 18
- 2
apps/files_versions/lib/Versions/VersionManager.php View File

@@ -31,11 +31,12 @@ use OCP\Files\IRootFolder;
use OCP\Files\Lock\ILock;
use OCP\Files\Lock\ILockManager;
use OCP\Files\Lock\LockContext;
use OCP\Files\Node;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\Lock\ManuallyLockedException;

class VersionManager implements IVersionManager, INameableVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend {
class VersionManager implements IVersionManager, INameableVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend, IMetadataVersionBackend {
/** @var (IVersionBackend[])[] */
private $backends = [];

@@ -160,6 +161,21 @@ class VersionManager implements IVersionManager, INameableVersionBackend, IDelet
}
}

public function setMetadataValue(Node $node, string $key, string $value): void {
$backend = $this->getBackendForStorage($node->getStorage());
if ($backend instanceof IMetadataVersionBackend) {
$backend->setMetadataValue($node, $key, $value);
}
}

public function getMetadataValue(Node $node, string $key): ?string {
$backend = $this->getBackendForStorage($node->getStorage());
if ($backend instanceof IMetadataVersionBackend) {
return $backend->getMetadataValue($node, $key);
}
return null;
}

/**
* Catch ManuallyLockedException and retry in app context if possible.
*
@@ -184,7 +200,7 @@ class VersionManager implements IVersionManager, INameableVersionBackend, IDelet
return $callback();
} catch (ManuallyLockedException $e) {
$owner = (string) $e->getOwner();
$appsThatHandleUpdates = array("text", "richdocuments");
$appsThatHandleUpdates = ["text", "richdocuments"];
if (!in_array($owner, $appsThatHandleUpdates)) {
throw $e;
}

+ 1
- 0
apps/files_versions/src/utils/davRequest.js View File

@@ -31,6 +31,7 @@ export default `<?xml version="1.0"?>
<d:getlastmodified />
<d:getetag />
<nc:version-label />
<nc:version-author />
<nc:has-preview />
</d:prop>
</d:propfind>`

+ 2
- 2
dist/files_versions-files_versions.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/files_versions-files_versions.js.map
File diff suppressed because it is too large
View File


+ 8
- 0
lib/composer/composer/autoload_static.php View File

@@ -17,6 +17,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\' => 3,
'OCP\\' => 4,
),
'B' =>
array (
'Bamarni\\Composer\\Bin\\' => 21,
),
);

public static $prefixDirsPsr4 = array (
@@ -32,6 +36,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
array (
0 => __DIR__ . '/../../..' . '/lib/public',
),
'Bamarni\\Composer\\Bin\\' =>
array (
0 => __DIR__ . '/..' . '/bamarni/composer-bin-plugin/src',
),
);

public static $fallbackDirsPsr4 = array (

Loading…
Cancel
Save