Merge pull request #23759 from nextcloud/backport/23752/stable20
[stable20] inform the user when flow config data exceeds thresholds
This commit is contained in:
commit
62f81da02e
|
@ -492,6 +492,11 @@ class Manager implements IManager {
|
||||||
if (count($checks) === 0) {
|
if (count($checks) === 0) {
|
||||||
throw new \UnexpectedValueException($this->l->t('At least one check needs to be provided'));
|
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);
|
$instance->validateOperation($name, $checks, $operation);
|
||||||
|
|
||||||
foreach ($checks as $check) {
|
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]));
|
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']);
|
$instance->validateCheck($check['operator'], $check['value']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ use OCP\IUserSession;
|
||||||
use OCP\SystemTag\ISystemTagManager;
|
use OCP\SystemTag\ISystemTagManager;
|
||||||
use OCP\WorkflowEngine\ICheck;
|
use OCP\WorkflowEngine\ICheck;
|
||||||
use OCP\WorkflowEngine\IEntity;
|
use OCP\WorkflowEngine\IEntity;
|
||||||
|
use OCP\WorkflowEngine\IEntityEvent;
|
||||||
use OCP\WorkflowEngine\IManager;
|
use OCP\WorkflowEngine\IManager;
|
||||||
use OCP\WorkflowEngine\IOperation;
|
use OCP\WorkflowEngine\IOperation;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
@ -435,4 +436,162 @@ class ManagerTest extends TestCase {
|
||||||
$this->assertSame(1, $entityTypeCounts[0]);
|
$this->assertSame(1, $entityTypeCounts[0]);
|
||||||
$this->assertSame(1, $entityTypeCounts[1]);
|
$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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,16 @@ interface IManager {
|
||||||
public const SCOPE_ADMIN = 0;
|
public const SCOPE_ADMIN = 0;
|
||||||
public const SCOPE_USER = 1;
|
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
|
* @depreacted Will be removed in NC19. Use the dedicated events in OCP\WorkflowEngine\Events
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue