From c2a52813e2cfadc43b096927ee9d9db3d9ac5c84 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 5 Sep 2019 15:52:11 +0200 Subject: [PATCH] extends ICheck with scope and entity support, provide them as initialState Signed-off-by: Arthur Schiwon --- .../lib/Check/AbstractStringCheck.php | 11 ++++ .../workflowengine/lib/Check/FileMimeType.php | 5 ++ apps/workflowengine/lib/Check/FileName.php | 9 +++ apps/workflowengine/lib/Check/FileSize.php | 9 +++ .../lib/Check/FileSystemTags.php | 9 +++ apps/workflowengine/lib/Check/RequestTime.php | 4 ++ .../lib/Check/RequestUserAgent.php | 4 ++ apps/workflowengine/lib/Manager.php | 56 +++++++++++++++++-- .../workflowengine/lib/Settings/ASettings.php | 21 +++++++ lib/public/WorkflowEngine/ICheck.php | 24 ++++++++ lib/public/WorkflowEngine/IManager.php | 17 ++++-- 11 files changed, 160 insertions(+), 9 deletions(-) diff --git a/apps/workflowengine/lib/Check/AbstractStringCheck.php b/apps/workflowengine/lib/Check/AbstractStringCheck.php index 0fd728e349..7a385729e0 100644 --- a/apps/workflowengine/lib/Check/AbstractStringCheck.php +++ b/apps/workflowengine/lib/Check/AbstractStringCheck.php @@ -25,6 +25,7 @@ namespace OCA\WorkflowEngine\Check; use OCP\Files\Storage\IStorage; use OCP\IL10N; use OCP\WorkflowEngine\ICheck; +use OCP\WorkflowEngine\IManager; abstract class AbstractStringCheck implements ICheck { @@ -101,6 +102,16 @@ abstract class AbstractStringCheck implements ICheck { } } + public function supportedEntities(): array { + // universal by default + return []; + } + + public function isAvailableForScope(int $scope): bool { + // admin only by default + return $scope === IManager::SCOPE_ADMIN; + } + /** * @param string $pattern * @param string $subject diff --git a/apps/workflowengine/lib/Check/FileMimeType.php b/apps/workflowengine/lib/Check/FileMimeType.php index 5f572f5aa9..6d51992fdd 100644 --- a/apps/workflowengine/lib/Check/FileMimeType.php +++ b/apps/workflowengine/lib/Check/FileMimeType.php @@ -22,6 +22,7 @@ namespace OCA\WorkflowEngine\Check; +use OCA\WorkflowEngine\Entity\File; use OCP\Files\IMimeTypeDetector; use OCP\Files\Storage\IStorage; use OCP\IL10N; @@ -195,4 +196,8 @@ class FileMimeType extends AbstractStringCheck { strpos($this->request->getPathInfo(), '/webdav/') === 0 ); } + + public function supportedEntities(): array { + return [ File::class ]; + } } diff --git a/apps/workflowengine/lib/Check/FileName.php b/apps/workflowengine/lib/Check/FileName.php index c6afbf7afa..d9b63ebfed 100644 --- a/apps/workflowengine/lib/Check/FileName.php +++ b/apps/workflowengine/lib/Check/FileName.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace OCA\WorkflowEngine\Check; +use OCA\WorkflowEngine\Entity\File; use OCP\Files\Storage\IStorage; use OCP\IL10N; use OCP\IRequest; @@ -75,4 +76,12 @@ class FileName extends AbstractStringCheck { } return parent::executeStringCheck($operator, $checkValue, $actualValue); } + + public function supportedEntities(): array { + return [ File::class ]; + } + + public function isAvailableForScope(int $scope): bool { + return true; + } } diff --git a/apps/workflowengine/lib/Check/FileSize.php b/apps/workflowengine/lib/Check/FileSize.php index 7e48f0f603..06a45bdcd4 100644 --- a/apps/workflowengine/lib/Check/FileSize.php +++ b/apps/workflowengine/lib/Check/FileSize.php @@ -22,6 +22,7 @@ namespace OCA\WorkflowEngine\Check; +use OCA\WorkflowEngine\Entity\File; use OCP\Files\Storage\IStorage; use OCP\IL10N; use OCP\IRequest; @@ -116,4 +117,12 @@ class FileSize implements ICheck { $this->size = $size; return $this->size; } + + public function supportedEntities(): array { + return [ File::class ]; + } + + public function isAvailableForScope(int $scope): bool { + return true; + } } diff --git a/apps/workflowengine/lib/Check/FileSystemTags.php b/apps/workflowengine/lib/Check/FileSystemTags.php index 4a2b87fd53..12285c9b33 100644 --- a/apps/workflowengine/lib/Check/FileSystemTags.php +++ b/apps/workflowengine/lib/Check/FileSystemTags.php @@ -22,6 +22,7 @@ namespace OCA\WorkflowEngine\Check; +use OCA\WorkflowEngine\Entity\File; use OCP\Files\Cache\ICache; use OCP\Files\IHomeStorage; use OCP\Files\Storage\IStorage; @@ -166,4 +167,12 @@ class FileSystemTags implements ICheck { $dir = dirname($path); return $dir === '.' ? '' : $dir; } + + public function supportedEntities(): array { + return [ File::class ]; + } + + public function isAvailableForScope(int $scope): bool { + return true; + } } diff --git a/apps/workflowengine/lib/Check/RequestTime.php b/apps/workflowengine/lib/Check/RequestTime.php index 2aa79e7767..0f5322b475 100644 --- a/apps/workflowengine/lib/Check/RequestTime.php +++ b/apps/workflowengine/lib/Check/RequestTime.php @@ -126,4 +126,8 @@ class RequestTime implements ICheck { throw new \UnexpectedValueException($this->l->t('The given end time is invalid'), 4); } } + + public function isAvailableForScope(int $scope): bool { + return true; + } } diff --git a/apps/workflowengine/lib/Check/RequestUserAgent.php b/apps/workflowengine/lib/Check/RequestUserAgent.php index 4191a2f341..2b2e301555 100644 --- a/apps/workflowengine/lib/Check/RequestUserAgent.php +++ b/apps/workflowengine/lib/Check/RequestUserAgent.php @@ -79,4 +79,8 @@ class RequestUserAgent extends AbstractStringCheck { protected function getActualValue() { return (string) $this->request->getHeader('User-Agent'); } + + public function isAvailableForScope(int $scope): bool { + return true; + } } diff --git a/apps/workflowengine/lib/Manager.php b/apps/workflowengine/lib/Manager.php index 8782fd3efe..3f01b890a5 100644 --- a/apps/workflowengine/lib/Manager.php +++ b/apps/workflowengine/lib/Manager.php @@ -21,10 +21,18 @@ namespace OCA\WorkflowEngine; - use OC\Files\Storage\Wrapper\Jail; use Doctrine\DBAL\DBALException; use OC\Cache\CappedMemoryCache; +use OCA\WorkflowEngine\Check\FileMimeType; +use OCA\WorkflowEngine\Check\FileName; +use OCA\WorkflowEngine\Check\FileSize; +use OCA\WorkflowEngine\Check\FileSystemTags; +use OCA\WorkflowEngine\Check\RequestRemoteAddress; +use OCA\WorkflowEngine\Check\RequestTime; +use OCA\WorkflowEngine\Check\RequestURL; +use OCA\WorkflowEngine\Check\RequestUserAgent; +use OCA\WorkflowEngine\Check\UserGroupMembership; use OCA\WorkflowEngine\Entity\File; use OCA\WorkflowEngine\Helper\ScopeContext; use OCP\AppFramework\QueryException; @@ -80,6 +88,9 @@ class Manager implements IManager, IEntityAware { /** @var IOperation[] */ protected $registeredOperators = []; + /** @var ICheck[] */ + protected $registeredChecks = []; + /** @var ILogger */ protected $logger; @@ -510,6 +521,12 @@ class Manager implements IManager, IEntityAware { throw new \UnexpectedValueException($this->l->t('Check %s is invalid', [$class])); } + if (!empty($instance->supportedEntities()) + && !in_array(get_class($entity), $instance->supportedEntities()) + ) { + throw new \UnexpectedValueException($this->l->t('Check %s is not allowed with this entity', [$class])); + } + $instance->validateCheck($check['operator'], $check['value']); } } @@ -653,11 +670,14 @@ class Manager implements IManager, IEntityAware { } /** - * Listen to 'OCP/WorkflowEngine::registerEntities' at the EventDispatcher - * for registering your entities - * - * @since 18.0.0 + * @return ICheck[] */ + public function getCheckList(): array { + $this->eventDispatcher->dispatch(IManager::EVENT_NAME_REG_CHECK, new GenericEvent($this)); + + return array_merge($this->getBuildInChecks(), $this->registeredChecks); + } + public function registerEntity(IEntity $entity): void { $this->registeredEntities[get_class($entity)] = $entity; } @@ -666,6 +686,10 @@ class Manager implements IManager, IEntityAware { $this->registeredOperators[get_class($operator)] = $operator; } + public function registerCheck(ICheck $check): void { + $this->registeredChecks[get_class($check)] = $check; + } + /** * @return IEntity[] */ @@ -693,4 +717,26 @@ class Manager implements IManager, IEntityAware { return []; } } + + /** + * @return IEntity[] + */ + protected function getBuildInChecks(): array { + try { + return [ + $this->container->query(FileMimeType::class), + $this->container->query(FileName::class), + $this->container->query(FileSize::class), + $this->container->query(FileSystemTags::class), + $this->container->query(RequestRemoteAddress::class), + $this->container->query(RequestTime::class), + $this->container->query(RequestURL::class), + $this->container->query(RequestUserAgent::class), + $this->container->query(UserGroupMembership::class), + ]; + } catch (QueryException $e) { + $this->logger->logException($e); + return []; + } + } } diff --git a/apps/workflowengine/lib/Settings/ASettings.php b/apps/workflowengine/lib/Settings/ASettings.php index 1781aaa2f5..ac2ebdb8ca 100644 --- a/apps/workflowengine/lib/Settings/ASettings.php +++ b/apps/workflowengine/lib/Settings/ASettings.php @@ -30,6 +30,7 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\IInitialStateService; use OCP\IL10N; use OCP\Settings\ISettings; +use OCP\WorkflowEngine\ICheck; use OCP\WorkflowEngine\IComplexOperation; use OCP\WorkflowEngine\IEntity; use OCP\WorkflowEngine\IEntityEvent; @@ -94,6 +95,13 @@ abstract class ASettings implements ISettings { $this->operatorsToArray($operators) ); + $checks = $this->manager->getCheckList(); + $this->initialStateService->provideInitialState( + Application::APP_ID, + 'checks', + $this->checksToArray($checks) + ); + $this->initialStateService->provideInitialState( Application::APP_ID, 'scope', @@ -156,4 +164,17 @@ abstract class ASettings implements ISettings { ]; }, $operators); } + + private function checksToArray(array $checks) { + $checks = array_filter($checks, function(ICheck $check) { + return $check->isAvailableForScope($this->getScope()); + }); + + return array_map(function (ICheck $check) { + return [ + 'id' => get_class($check), + 'supportedEntities' => $check->supportedEntities(), + ]; + }, $checks); + } } diff --git a/lib/public/WorkflowEngine/ICheck.php b/lib/public/WorkflowEngine/ICheck.php index 1d4fc96646..92ec6f8389 100644 --- a/lib/public/WorkflowEngine/ICheck.php +++ b/lib/public/WorkflowEngine/ICheck.php @@ -55,4 +55,28 @@ interface ICheck { * @since 9.1 */ public function validateCheck($operator, $value); + + /** + * returns a list of Entities the checker supports. The values must match + * the class name of the entity. + * + * An empty result means the check is universally available. + * + * @since 18.0.0 + */ + public function supportedEntities(): array; + + /** + * returns whether the operation can be used in the requested scope. + * + * Scope IDs are defined as constants in OCP\WorkflowEngine\IManager. At + * time of writing these are SCOPE_ADMIN and SCOPE_USER. + * + * For possibly unknown future scopes the recommended behaviour is: if + * user scope is permitted, the default behaviour should return `true`, + * otherwise `false`. + * + * @since 18.0.0 + */ + public function isAvailableForScope(int $scope): bool; } diff --git a/lib/public/WorkflowEngine/IManager.php b/lib/public/WorkflowEngine/IManager.php index 8ef7a3a03e..8be47d961e 100644 --- a/lib/public/WorkflowEngine/IManager.php +++ b/lib/public/WorkflowEngine/IManager.php @@ -39,6 +39,7 @@ interface IManager { const EVENT_NAME_REG_OPERATION = 'OCP\WorkflowEngine::registerOperations'; const EVENT_NAME_REG_ENTITY = 'OCP\WorkflowEngine::registerEntities'; + const EVENT_NAME_REG_CHECK = 'OCP\WorkflowEngine::registerChecks'; /** * @param IStorage $storage @@ -56,18 +57,26 @@ interface IManager { public function getMatchingOperations($class, $returnFirstMatchingOperationOnly = true); /** - * Listen to 'OCP/WorkflowEngine::registerEntities' at the EventDispatcher - * for registering your entities + * Listen to `\OCP\WorkflowEngine::EVENT_NAME_REG_ENTITY` at the + * EventDispatcher for registering your entities. * * @since 18.0.0 */ public function registerEntity(IEntity $entity): void; /** - * Listen to 'OCP/WorkflowEngine::registerOperators' at the EventDispatcher - * for registering your operators + * Listen to `\OCP\WorkflowEngine::EVENT_NAME_REG_OPERATION` at the + * EventDispatcher for registering your operators. * * @since 18.0.0 */ public function registerOperation(IOperation $operator): void; + + /** + * Listen to `\OCP\WorkflowEngine::EVENT_NAME_REG_CHECK` at the + * EventDispatcher for registering your operators. + * + * @since 18.0.0 + */ + public function registerCheck(ICheck $check): void; }