diff options
author | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2020-10-28 14:07:14 +0100 |
---|---|---|
committer | backportbot[bot] <backportbot[bot]@users.noreply.github.com> | 2020-10-28 15:11:14 +0000 |
commit | 4967d5b2babb4013b052053239415e5f886a1121 (patch) | |
tree | b272fa5fb0516ef133f8ca346a983aee134550fa | |
parent | 4d20a63d4f1fd5603ccc17c22dd06e51a4caf100 (diff) | |
download | nextcloud-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.php | 9 | ||||
-rw-r--r-- | apps/workflowengine/tests/ManagerTest.php | 159 | ||||
-rw-r--r-- | lib/public/WorkflowEngine/IManager.php | 10 |
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'; |