aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@arthur-schiwon.de>2020-10-28 14:07:14 +0100
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>2020-10-28 15:11:14 +0000
commit4967d5b2babb4013b052053239415e5f886a1121 (patch)
treeb272fa5fb0516ef133f8ca346a983aee134550fa
parent4d20a63d4f1fd5603ccc17c22dd06e51a4caf100 (diff)
downloadnextcloud-server-4967d5b2babb4013b052053239415e5f886a1121.tar.gz
nextcloud-server-4967d5b2babb4013b052053239415e5f886a1121.zip
inform the user when flow config data exceeds thresholds
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
-rw-r--r--apps/workflowengine/lib/Manager.php9
-rw-r--r--apps/workflowengine/tests/ManagerTest.php159
-rw-r--r--lib/public/WorkflowEngine/IManager.php10
3 files changed, 178 insertions, 0 deletions
diff --git a/apps/workflowengine/lib/Manager.php b/apps/workflowengine/lib/Manager.php
index fefeb9230e6..f3cf7621058 100644
--- a/apps/workflowengine/lib/Manager.php
+++ b/apps/workflowengine/lib/Manager.php
@@ -492,6 +492,11 @@ class Manager implements IManager {
if (count($checks) === 0) {
throw new \UnexpectedValueException($this->l->t('At least one check needs to be provided'));
}
+
+ if (strlen((string)$operation) > IManager::MAX_OPERATION_VALUE_BYTES) {
+ throw new \UnexpectedValueException($this->l->t('The provided operation data is too long'));
+ }
+
$instance->validateOperation($name, $checks, $operation);
foreach ($checks as $check) {
@@ -516,6 +521,10 @@ class Manager implements IManager {
throw new \UnexpectedValueException($this->l->t('Check %s is not allowed with this entity', [$class]));
}
+ if (strlen((string)$check['value']) > IManager::MAX_CHECK_VALUE_BYTES) {
+ throw new \UnexpectedValueException($this->l->t('The provided check value is too long'));
+ }
+
$instance->validateCheck($check['operator'], $check['value']);
}
}
diff --git a/apps/workflowengine/tests/ManagerTest.php b/apps/workflowengine/tests/ManagerTest.php
index 512d5dc1f61..7d22e910b6d 100644
--- a/apps/workflowengine/tests/ManagerTest.php
+++ b/apps/workflowengine/tests/ManagerTest.php
@@ -37,6 +37,7 @@ use OCP\IUserSession;
use OCP\SystemTag\ISystemTagManager;
use OCP\WorkflowEngine\ICheck;
use OCP\WorkflowEngine\IEntity;
+use OCP\WorkflowEngine\IEntityEvent;
use OCP\WorkflowEngine\IManager;
use OCP\WorkflowEngine\IOperation;
use PHPUnit\Framework\MockObject\MockObject;
@@ -433,4 +434,162 @@ class ManagerTest extends TestCase {
$this->assertSame(1, $entityTypeCounts[0]);
$this->assertSame(1, $entityTypeCounts[1]);
}
+
+ public function testValidateOperationOK() {
+ $check = [
+ 'class' => ICheck::class,
+ 'operator' => 'is',
+ 'value' => 'barfoo',
+ ];
+
+ $operationMock = $this->createMock(IOperation::class);
+ $entityMock = $this->createMock(IEntity::class);
+ $eventEntityMock = $this->createMock(IEntityEvent::class);
+ $checkMock = $this->createMock(ICheck::class);
+
+ $operationMock->expects($this->once())
+ ->method('validateOperation')
+ ->with('test', [$check], 'operationData');
+
+ $entityMock->expects($this->any())
+ ->method('getEvents')
+ ->willReturn([$eventEntityMock]);
+
+ $eventEntityMock->expects($this->any())
+ ->method('getEventName')
+ ->willReturn('MyEvent');
+
+ $checkMock->expects($this->any())
+ ->method('supportedEntities')
+ ->willReturn([IEntity::class]);
+ $checkMock->expects($this->atLeastOnce())
+ ->method('validateCheck');
+
+ $this->container->expects($this->any())
+ ->method('query')
+ ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
+ switch ($className) {
+ case IOperation::class:
+ return $operationMock;
+ case IEntity::class:
+ return $entityMock;
+ case IEntityEvent::class:
+ return $eventEntityMock;
+ case ICheck::class:
+ return $checkMock;
+ default:
+ return $this->createMock($className);
+ }
+ });
+
+ $this->manager->validateOperation(IOperation::class, 'test', [$check], 'operationData', IEntity::class, ['MyEvent']);
+ }
+
+ public function testValidateOperationCheckInputLengthError() {
+ $check = [
+ 'class' => ICheck::class,
+ 'operator' => 'is',
+ 'value' => str_pad('', IManager::MAX_CHECK_VALUE_BYTES + 1, 'FooBar'),
+ ];
+
+ $operationMock = $this->createMock(IOperation::class);
+ $entityMock = $this->createMock(IEntity::class);
+ $eventEntityMock = $this->createMock(IEntityEvent::class);
+ $checkMock = $this->createMock(ICheck::class);
+
+ $operationMock->expects($this->once())
+ ->method('validateOperation')
+ ->with('test', [$check], 'operationData');
+
+ $entityMock->expects($this->any())
+ ->method('getEvents')
+ ->willReturn([$eventEntityMock]);
+
+ $eventEntityMock->expects($this->any())
+ ->method('getEventName')
+ ->willReturn('MyEvent');
+
+ $checkMock->expects($this->any())
+ ->method('supportedEntities')
+ ->willReturn([IEntity::class]);
+ $checkMock->expects($this->never())
+ ->method('validateCheck');
+
+ $this->container->expects($this->any())
+ ->method('query')
+ ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
+ switch ($className) {
+ case IOperation::class:
+ return $operationMock;
+ case IEntity::class:
+ return $entityMock;
+ case IEntityEvent::class:
+ return $eventEntityMock;
+ case ICheck::class:
+ return $checkMock;
+ default:
+ return $this->createMock($className);
+ }
+ });
+
+ try {
+ $this->manager->validateOperation(IOperation::class, 'test', [$check], 'operationData', IEntity::class, ['MyEvent']);
+ } catch (\UnexpectedValueException $e) {
+ $this->assertSame('The provided check value is too long', $e->getMessage());
+ }
+ }
+
+ public function testValidateOperationDataLengthError() {
+ $check = [
+ 'class' => ICheck::class,
+ 'operator' => 'is',
+ 'value' => 'barfoo',
+ ];
+ $operationData = str_pad('', IManager::MAX_OPERATION_VALUE_BYTES + 1, 'FooBar');
+
+ $operationMock = $this->createMock(IOperation::class);
+ $entityMock = $this->createMock(IEntity::class);
+ $eventEntityMock = $this->createMock(IEntityEvent::class);
+ $checkMock = $this->createMock(ICheck::class);
+
+ $operationMock->expects($this->never())
+ ->method('validateOperation');
+
+ $entityMock->expects($this->any())
+ ->method('getEvents')
+ ->willReturn([$eventEntityMock]);
+
+ $eventEntityMock->expects($this->any())
+ ->method('getEventName')
+ ->willReturn('MyEvent');
+
+ $checkMock->expects($this->any())
+ ->method('supportedEntities')
+ ->willReturn([IEntity::class]);
+ $checkMock->expects($this->never())
+ ->method('validateCheck');
+
+ $this->container->expects($this->any())
+ ->method('query')
+ ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
+ switch ($className) {
+ case IOperation::class:
+ return $operationMock;
+ case IEntity::class:
+ return $entityMock;
+ case IEntityEvent::class:
+ return $eventEntityMock;
+ case ICheck::class:
+ return $checkMock;
+ default:
+ return $this->createMock($className);
+ }
+ });
+
+ try {
+ $this->manager->validateOperation(IOperation::class, 'test', [$check], $operationData, IEntity::class, ['MyEvent']);
+ } catch (\UnexpectedValueException $e) {
+ $this->assertSame('The provided operation data is too long', $e->getMessage());
+ }
+ }
}
diff --git a/lib/public/WorkflowEngine/IManager.php b/lib/public/WorkflowEngine/IManager.php
index a1c8833bef3..df8c276bbcd 100644
--- a/lib/public/WorkflowEngine/IManager.php
+++ b/lib/public/WorkflowEngine/IManager.php
@@ -36,6 +36,16 @@ interface IManager {
public const SCOPE_USER = 1;
/**
+ * @since 21.0.0
+ */
+ public const MAX_CHECK_VALUE_BYTES = 2048;
+
+ /**
+ * @since 21.0.0
+ */
+ public const MAX_OPERATION_VALUE_BYTES = 4096;
+
+ /**
* @depreacted Will be removed in NC19. Use the dedicated events in OCP\WorkflowEngine\Events
*/
public const EVENT_NAME_REG_OPERATION = 'OCP\WorkflowEngine::registerOperations';