Skip to content

Commit cba993d

Browse files
Merge pull request #132 from nextcloud/enh/noid/workflow-18
Move to new operation interface for Nextcloud 18
2 parents cd5de2d + 731a5de commit cba993d

7 files changed

Lines changed: 116 additions & 332 deletions

File tree

appinfo/info.xml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
## How it works
1010
The administrator can create and manage a set of rule groups. Each of the rule groups consists of one or more rules. If all rules of a group hold true, the group matches the request and access is being denied or the upload is blocked. The rules criteria range from IP address, mimetype and request time to group membership, tags, user agent and more.
11-
11+
1212
An example would be to deny access to MS Excel/XLSX files owned by the "Human Resources" group accessed from an IP not on the internal company network or to block uploads of files bigger than 512 mb by students in the "1st year" group.
13-
13+
1414
Learn more about File Access Control on [https://nextcloud.com/workflow](https://nextcloud.com/workflow)</description>
1515

1616
<version>1.8.0</version>
@@ -36,9 +36,4 @@ Learn more about File Access Control on [https://nextcloud.com/workflow](https:/
3636
<dependencies>
3737
<nextcloud min-version="18" max-version="18" />
3838
</dependencies>
39-
40-
<settings>
41-
<admin>OCA\FilesAccessControl\Settings\Admin</admin>
42-
<admin-section>OCA\FilesAccessControl\Settings\Section</admin-section>
43-
</settings>
4439
</info>

js/admin.js

Lines changed: 5 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -19,77 +19,9 @@
1919
*/
2020

2121
(function() {
22-
OCA.FilesAccessControl = OCA.FilesAccessControl || {};
23-
24-
/**
25-
* @class OCA.FilesAccessControl.Operation
26-
*/
27-
OCA.FilesAccessControl.Operation =
28-
OCA.WorkflowEngine.Operation.extend({
29-
defaults: {
30-
'class': 'OCA\\FilesAccessControl\\Operation',
31-
'name': '',
32-
'checks': [],
33-
'operation': 'deny'
34-
}
35-
});
36-
37-
/**
38-
* @class OCA.FilesAccessControl.OperationsCollection
39-
*
40-
* collection for all configurated operations
41-
*/
42-
OCA.FilesAccessControl.OperationsCollection =
43-
OCA.WorkflowEngine.OperationsCollection.extend({
44-
model: OCA.FilesAccessControl.Operation
45-
});
46-
47-
/**
48-
* @class OCA.FilesAccessControl.OperationView
49-
*
50-
* this creates the view for a single operation
51-
*/
52-
OCA.FilesAccessControl.OperationView =
53-
OCA.WorkflowEngine.OperationView.extend({
54-
model: OCA.FilesAccessControl.Operation,
55-
render: function() {
56-
var $el = OCA.WorkflowEngine.OperationView.prototype.render.apply(this);
57-
$el.find('input.operation-operation').addClass('hidden');
58-
}
59-
});
60-
61-
/**
62-
* @class OCA.FilesAccessControl.OperationsView
63-
*
64-
* this creates the view for configured operations
65-
*/
66-
OCA.FilesAccessControl.OperationsView =
67-
OCA.WorkflowEngine.OperationsView.extend({
68-
initialize: function() {
69-
OCA.WorkflowEngine.OperationsView.prototype.initialize.apply(this, [
70-
'OCA\\FilesAccessControl\\Operation'
71-
]);
72-
},
73-
renderOperation: function(operation) {
74-
var subView = new OCA.FilesAccessControl.OperationView({
75-
model: operation
76-
});
77-
78-
OCA.WorkflowEngine.OperationsView.prototype.renderOperation.apply(this, [
79-
subView
80-
]);
81-
}
82-
});
22+
OCA.WorkflowEngine.registerOperator({
23+
id: 'OCA\\FilesAccessControl\\Operation',
24+
color: '#ca2b2b',
25+
operation: 'deny',
26+
})
8327
})();
84-
85-
86-
$(document).ready(function() {
87-
OC.SystemTags.collection.fetch({
88-
success: function() {
89-
new OCA.FilesAccessControl.OperationsView({
90-
el: '#files_accesscontrol .rules',
91-
collection: new OCA.FilesAccessControl.OperationsCollection()
92-
});
93-
}
94-
});
95-
});

lib/AppInfo/Application.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222
namespace OCA\FilesAccessControl\AppInfo;
2323

2424
use OC\Files\Filesystem;
25+
use OCA\FilesAccessControl\Operation;
2526
use OCA\FilesAccessControl\StorageWrapper;
27+
use OCA\WorkflowEngine\Manager;
2628
use OCP\Files\Storage\IStorage;
2729
use OCP\Util;
30+
use OCP\WorkflowEngine\IManager;
31+
use Symfony\Component\EventDispatcher\GenericEvent;
2832

2933
class Application extends \OCP\AppFramework\App {
3034

@@ -36,7 +40,14 @@ public function __construct() {
3640
* Register all hooks and listeners
3741
*/
3842
public function registerHooksAndListeners() {
43+
$container = $this->getContainer();
3944
Util::connectHook('OC_Filesystem', 'preSetup', $this, 'addStorageWrapper');
45+
$container->getServer()->getEventDispatcher()->addListener(IManager::EVENT_NAME_REG_OPERATION, function (GenericEvent $event) use ($container){
46+
$operation = $container->query(Operation::class);
47+
$event->getSubject()->registerOperation($operation);
48+
Util::addScript('files_accesscontrol', 'admin');
49+
});
50+
4051
}
4152

4253
/**

lib/Operation.php

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,38 @@
2222
namespace OCA\FilesAccessControl;
2323

2424

25+
use OCA\WorkflowEngine\Entity\File;
26+
use OCP\EventDispatcher\Event;
2527
use OCP\Files\ForbiddenException;
2628
use OCP\Files\Storage\IStorage;
2729
use OCP\IL10N;
30+
use OCP\IURLGenerator;
31+
use OCP\WorkflowEngine\IComplexOperation;
2832
use OCP\WorkflowEngine\IManager;
29-
use OCP\WorkflowEngine\IOperation;
33+
use OCP\WorkflowEngine\IRuleMatcher;
34+
use OCP\WorkflowEngine\ISpecificOperation;
3035

31-
class Operation implements IOperation{
36+
class Operation implements IComplexOperation, ISpecificOperation {
3237
/** @var IManager */
3338
protected $manager;
3439

3540
/** @var IL10N */
3641
protected $l;
3742

43+
/** @var IURLGenerator */
44+
protected $urlGenerator;
45+
3846
/** @var int */
3947
protected $nestingLevel = 0;
4048

4149
/**
4250
* @param IManager $manager
4351
* @param IL10N $l
4452
*/
45-
public function __construct(IManager $manager, IL10N $l) {
53+
public function __construct(IManager $manager, IL10N $l, IURLGenerator $urlGenerator) {
4654
$this->manager = $manager;
4755
$this->l = $l;
56+
$this->urlGenerator = $urlGenerator;
4857
}
4958

5059
/**
@@ -63,8 +72,9 @@ public function checkFileAccess(IStorage $storage, $path) {
6372
$this->nestingLevel++;
6473

6574
$filePath = $this->translatePath($storage, $path);
66-
$this->manager->setFileInfo($storage, $filePath);
67-
$match = $this->manager->getMatchingOperations('OCA\FilesAccessControl\Operation');
75+
$ruleMatcher = $this->manager->getRuleMatcher();
76+
$ruleMatcher->setFileInfo($storage, $filePath);
77+
$match = $ruleMatcher->getMatchingOperations(self::class);
6878

6979
$this->nestingLevel--;
7080

@@ -166,9 +176,91 @@ protected function isCreatingSkeletonFiles() {
166176
* @param string $operation
167177
* @throws \UnexpectedValueException
168178
*/
169-
public function validateOperation($name, array $checks, $operation) {
179+
public function validateOperation(string $name, array $checks, string $operation): void {
170180
if (empty($checks)) {
171181
throw new \UnexpectedValueException($this->l->t('No rule given'));
172182
}
173183
}
184+
185+
/**
186+
* returns a translated name to be presented in the web interface
187+
*
188+
* Example: "Automated tagging" (en), "Aŭtomata etikedado" (eo)
189+
*
190+
* @since 18.0.0
191+
*/
192+
public function getDisplayName(): string {
193+
return $this->l->t('Block access to a file');
194+
}
195+
196+
/**
197+
* returns a translated, descriptive text to be presented in the web interface.
198+
*
199+
* It should be short and precise.
200+
*
201+
* Example: "Tag based automatic deletion of files after a given time." (en)
202+
*
203+
* @since 18.0.0
204+
*/
205+
public function getDescription(): string {
206+
return '';
207+
}
208+
209+
/**
210+
* returns the URL to the icon of the operator for display in the web interface.
211+
*
212+
* Usually, the implementation would utilize the `imagePath()` method of the
213+
* `\OCP\IURLGenerator` instance and simply return its result.
214+
*
215+
* Example implementation: return $this->urlGenerator->imagePath('myApp', 'cat.svg');
216+
*
217+
* @since 18.0.0
218+
*/
219+
public function getIcon(): string {
220+
return $this->urlGenerator->imagePath('files_accesscontrol', 'app.svg');
221+
}
222+
223+
/**
224+
* returns whether the operation can be used in the requested scope.
225+
*
226+
* Scope IDs are defined as constants in OCP\WorkflowEngine\IManager. At
227+
* time of writing these are SCOPE_ADMIN and SCOPE_USER.
228+
*
229+
* For possibly unknown future scopes the recommended behaviour is: if
230+
* user scope is permitted, the default behaviour should return `true`,
231+
* otherwise `false`.
232+
*
233+
* @since 18.0.0
234+
*/
235+
public function isAvailableForScope(int $scope): bool {
236+
return $scope === IManager::SCOPE_ADMIN;
237+
}
238+
239+
/**
240+
* returns the id of the entity the operator is designed for
241+
*
242+
* Example: 'WorkflowEngine_Entity_File'
243+
*
244+
* @since 18.0.0
245+
*/
246+
public function getEntityId(): string {
247+
return File::class;
248+
}
249+
250+
/**
251+
* As IComplexOperation chooses the triggering events itself, a hint has
252+
* to be shown to the user so make clear when this operation is becoming
253+
* active. This method returns such a translated string.
254+
*
255+
* Example: "When a file is accessed" (en)
256+
*
257+
* @since 18.0.0
258+
*/
259+
public function getTriggerHint(): string {
260+
return $this->l->t('File is accessed');
261+
}
262+
263+
public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatcher): void {
264+
// Noop
265+
}
174266
}

lib/Settings/Admin.php

Lines changed: 0 additions & 86 deletions
This file was deleted.

0 commit comments

Comments
 (0)