Skip to content

Commit 97d996f

Browse files
Merge pull request #60904 from nextcloud/backport/59610/stable34
[stable34] feat(files_versions): allow to block version creation using WFE
2 parents de17cda + 9eecb73 commit 97d996f

14 files changed

Lines changed: 215 additions & 1 deletion

apps/files_versions/composer/composer/autoload_classmap.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
1010
'OCA\\Files_Versions\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
1111
'OCA\\Files_Versions\\BackgroundJob\\ExpireVersions' => $baseDir . '/../lib/BackgroundJob/ExpireVersions.php',
12+
'OCA\\Files_Versions\\BlockVersioningOperation' => $baseDir . '/../lib/BlockVersioningOperation.php',
1213
'OCA\\Files_Versions\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
1314
'OCA\\Files_Versions\\Command\\CleanUp' => $baseDir . '/../lib/Command/CleanUp.php',
1415
'OCA\\Files_Versions\\Command\\Expire' => $baseDir . '/../lib/Command/Expire.php',
@@ -20,10 +21,12 @@
2021
'OCA\\Files_Versions\\Events\\VersionCreatedEvent' => $baseDir . '/../lib/Events/VersionCreatedEvent.php',
2122
'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => $baseDir . '/../lib/Events/VersionRestoredEvent.php',
2223
'OCA\\Files_Versions\\Expiration' => $baseDir . '/../lib/Expiration.php',
24+
'OCA\\Files_Versions\\Listener\\CreateVersionListenerForWorkflow' => $baseDir . '/../lib/Listener/CreateVersionListenerForWorkflow.php',
2325
'OCA\\Files_Versions\\Listener\\FileEventsListener' => $baseDir . '/../lib/Listener/FileEventsListener.php',
2426
'OCA\\Files_Versions\\Listener\\LegacyRollbackListener' => $baseDir . '/../lib/Listener/LegacyRollbackListener.php',
2527
'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
2628
'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
29+
'OCA\\Files_Versions\\Listener\\RegisterWorkflowIntegrationListener' => $baseDir . '/../lib/Listener/RegisterWorkflowIntegrationListener.php',
2730
'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => $baseDir . '/../lib/Listener/VersionAuthorListener.php',
2831
'OCA\\Files_Versions\\Listener\\VersionStorageMoveListener' => $baseDir . '/../lib/Listener/VersionStorageMoveListener.php',
2932
'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => $baseDir . '/../lib/Migration/Version1020Date20221114144058.php',

apps/files_versions/composer/composer/autoload_static.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ComposerStaticInitFiles_Versions
2424
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
2525
'OCA\\Files_Versions\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
2626
'OCA\\Files_Versions\\BackgroundJob\\ExpireVersions' => __DIR__ . '/..' . '/../lib/BackgroundJob/ExpireVersions.php',
27+
'OCA\\Files_Versions\\BlockVersioningOperation' => __DIR__ . '/..' . '/../lib/BlockVersioningOperation.php',
2728
'OCA\\Files_Versions\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
2829
'OCA\\Files_Versions\\Command\\CleanUp' => __DIR__ . '/..' . '/../lib/Command/CleanUp.php',
2930
'OCA\\Files_Versions\\Command\\Expire' => __DIR__ . '/..' . '/../lib/Command/Expire.php',
@@ -35,10 +36,12 @@ class ComposerStaticInitFiles_Versions
3536
'OCA\\Files_Versions\\Events\\VersionCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/VersionCreatedEvent.php',
3637
'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/VersionRestoredEvent.php',
3738
'OCA\\Files_Versions\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php',
39+
'OCA\\Files_Versions\\Listener\\CreateVersionListenerForWorkflow' => __DIR__ . '/..' . '/../lib/Listener/CreateVersionListenerForWorkflow.php',
3840
'OCA\\Files_Versions\\Listener\\FileEventsListener' => __DIR__ . '/..' . '/../lib/Listener/FileEventsListener.php',
3941
'OCA\\Files_Versions\\Listener\\LegacyRollbackListener' => __DIR__ . '/..' . '/../lib/Listener/LegacyRollbackListener.php',
4042
'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
4143
'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
44+
'OCA\\Files_Versions\\Listener\\RegisterWorkflowIntegrationListener' => __DIR__ . '/..' . '/../lib/Listener/RegisterWorkflowIntegrationListener.php',
4245
'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => __DIR__ . '/..' . '/../lib/Listener/VersionAuthorListener.php',
4346
'OCA\\Files_Versions\\Listener\\VersionStorageMoveListener' => __DIR__ . '/..' . '/../lib/Listener/VersionStorageMoveListener.php',
4447
'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => __DIR__ . '/..' . '/../lib/Migration/Version1020Date20221114144058.php',

apps/files_versions/lib/AppInfo/Application.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
use OCA\Files\Event\LoadAdditionalScriptsEvent;
1212
use OCA\Files\Event\LoadSidebar;
1313
use OCA\Files_Versions\Capabilities;
14+
use OCA\Files_Versions\Events\CreateVersionEvent;
1415
use OCA\Files_Versions\Events\VersionRestoredEvent;
16+
use OCA\Files_Versions\Listener\CreateVersionListenerForWorkflow;
1517
use OCA\Files_Versions\Listener\FileEventsListener;
1618
use OCA\Files_Versions\Listener\LegacyRollbackListener;
1719
use OCA\Files_Versions\Listener\LoadAdditionalListener;
1820
use OCA\Files_Versions\Listener\LoadSidebarListener;
21+
use OCA\Files_Versions\Listener\RegisterWorkflowIntegrationListener;
1922
use OCA\Files_Versions\Listener\VersionAuthorListener;
2023
use OCA\Files_Versions\Listener\VersionStorageMoveListener;
2124
use OCA\Files_Versions\Versions\IVersionManager;
@@ -36,6 +39,8 @@
3639
use OCP\Files\Events\Node\NodeRenamedEvent;
3740
use OCP\Files\Events\Node\NodeTouchedEvent;
3841
use OCP\Files\Events\Node\NodeWrittenEvent;
42+
use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
43+
use OCP\WorkflowEngine\Events\RegisterOperationsEvent;
3944
use Psr\Container\ContainerInterface;
4045
use Psr\Log\LoggerInterface;
4146

@@ -85,8 +90,12 @@ public function register(IRegistrationContext $context): void {
8590

8691
// we add the version author listener with lower priority to make sure new versions already are created by FileEventsListener
8792
$context->registerEventListener(NodeWrittenEvent::class, VersionAuthorListener::class, -1);
88-
8993
$context->registerEventListener(VersionRestoredEvent::class, LegacyRollbackListener::class);
94+
95+
// WFE integration
96+
$context->registerEventListener(RegisterOperationsEvent::class, RegisterWorkflowIntegrationListener::class);
97+
$context->registerEventListener(LoadSettingsScriptsEvent::class, RegisterWorkflowIntegrationListener::class);
98+
$context->registerEventListener(CreateVersionEvent::class, CreateVersionListenerForWorkflow::class);
9099
}
91100

92101
#[\Override]
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*!
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OCA\Files_Versions;
10+
11+
use OCA\Files_Versions\Events\CreateVersionEvent;
12+
use OCA\WorkflowEngine\Entity\File as FileEntity;
13+
use OCP\EventDispatcher\Event;
14+
use OCP\Files\Folder;
15+
use OCP\IL10N;
16+
use OCP\IURLGenerator;
17+
use OCP\WorkflowEngine\IComplexOperation;
18+
use OCP\WorkflowEngine\IManager;
19+
use OCP\WorkflowEngine\IRuleMatcher;
20+
use OCP\WorkflowEngine\ISpecificOperation;
21+
use Psr\Log\LoggerInterface;
22+
23+
class BlockVersioningOperation implements ISpecificOperation, IComplexOperation {
24+
25+
public function __construct(
26+
private readonly IL10N $l10n,
27+
private readonly FileEntity $fileEntity,
28+
private readonly LoggerInterface $logger,
29+
private readonly IURLGenerator $urlGenerator,
30+
) {
31+
}
32+
33+
#[\Override]
34+
public function getEntityId(): string {
35+
return FileEntity::class;
36+
}
37+
38+
#[\Override]
39+
public function getDisplayName(): string {
40+
return $this->l10n->t('Block file versioning');
41+
}
42+
43+
#[\Override]
44+
public function getDescription(): string {
45+
return $this->l10n->t('Automatic tag based blocking of file version creation.');
46+
}
47+
48+
#[\Override]
49+
public function getIcon(): string {
50+
return $this->urlGenerator->imagePath('files_versions', 'app.svg');
51+
}
52+
53+
#[\Override]
54+
public function isAvailableForScope(int $scope): bool {
55+
return $scope === IManager::SCOPE_ADMIN;
56+
}
57+
58+
#[\Override]
59+
public function validateOperation(string $name, array $checks, string $operation): void {
60+
if (empty($checks)) {
61+
throw new \UnexpectedValueException($this->l10n->t('No rule given'));
62+
}
63+
}
64+
65+
#[\Override]
66+
public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatcher): void {
67+
if ($eventName !== CreateVersionEvent::class || !($event instanceof CreateVersionEvent)) {
68+
return;
69+
}
70+
71+
$node = $event->getNode();
72+
$path = $node->getInternalPath();
73+
74+
$ruleMatcher->setFileInfo(
75+
$node->getStorage(),
76+
$path,
77+
$node instanceof Folder,
78+
);
79+
$ruleMatcher->setEntitySubject($this->fileEntity, $node);
80+
$ruleMatcher->setOperation($this);
81+
$flows = $ruleMatcher->getFlows();
82+
83+
if ($flows !== []) {
84+
$this->logger->debug('Blocking version creation due to matching workflow rules', [
85+
'path' => $path,
86+
]);
87+
$event->disableVersions();
88+
}
89+
}
90+
91+
#[\Override]
92+
public function getTriggerHint(): string {
93+
return $this->l10n->t('A new version is created'); // TRANSLATORS: This will be shown as "When: " "A new version is created"
94+
}
95+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*!
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OCA\Files_Versions\Listener;
10+
11+
use OCA\Files_Versions\BlockVersioningOperation;
12+
use OCA\Files_Versions\Events\CreateVersionEvent;
13+
use OCP\EventDispatcher\Event;
14+
use OCP\EventDispatcher\IEventListener;
15+
use OCP\WorkflowEngine\IManager;
16+
17+
/** @template-implements IEventListener<CreateVersionEvent> */
18+
class CreateVersionListenerForWorkflow implements IEventListener {
19+
20+
public function __construct(
21+
private IManager $manager,
22+
private BlockVersioningOperation $operation,
23+
) {
24+
}
25+
26+
#[\Override]
27+
public function handle(Event $event): void {
28+
if (!($event instanceof CreateVersionEvent)) {
29+
return;
30+
}
31+
32+
$this->operation->onEvent(
33+
$event::class,
34+
$event,
35+
$this->manager->getRuleMatcher(),
36+
);
37+
}
38+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*!
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OCA\Files_Versions\Listener;
10+
11+
use OCA\Files_Versions\BlockVersioningOperation;
12+
use OCP\EventDispatcher\Event;
13+
use OCP\EventDispatcher\IEventListener;
14+
use OCP\Util;
15+
use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
16+
use OCP\WorkflowEngine\Events\RegisterOperationsEvent;
17+
18+
/** @template-implements IEventListener<RegisterOperationsEvent|LoadSettingsScriptsEvent> */
19+
class RegisterWorkflowIntegrationListener implements IEventListener {
20+
21+
public function __construct(
22+
private readonly BlockVersioningOperation $operation,
23+
) {
24+
}
25+
26+
#[\Override]
27+
public function handle(Event $event): void {
28+
if ($event instanceof RegisterOperationsEvent) {
29+
$event->registerOperation($this->operation);
30+
} elseif ($event instanceof LoadSettingsScriptsEvent) {
31+
Util::addScript('files_versions', 'workflow', 'workflowengine');
32+
}
33+
}
34+
}

apps/files_versions/lib/Storage.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ public static function store($filename) {
205205
}
206206

207207
$event = new CreateVersionEvent($file);
208+
$eventDispatcher->dispatchTyped($event);
208209
$eventDispatcher->dispatch('OCA\Files_Versions::createVersion', $event);
209210
if ($event->shouldCreateVersion() === false) {
210211
return false;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*!
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
window.addEventListener('DOMContentLoaded', () => {
7+
globalThis.OCA.WorkflowEngine.registerOperator({
8+
id: 'OCA\\Files_Versions\\BlockVersioningOperation',
9+
color: '#ff5900',
10+
operation: 'deny',
11+
})
12+
})

build/frontend/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const modules = {
4848
},
4949
files_versions: {
5050
'sidebar-tab': resolve(import.meta.dirname, 'apps/files_versions/src', 'sidebar_tab.ts'),
51+
workflow: resolve(import.meta.dirname, 'apps/files_versions/src', 'workflow.ts'),
5152
},
5253
oauth2: {
5354
'settings-admin': resolve(import.meta.dirname, 'apps/oauth2/src', 'settings-admin.ts'),

dist/files_versions-workflow.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* extracted by css-entry-points-plugin */

0 commit comments

Comments
 (0)