From 8c72bf9abe431011f980ef6ed2a436d486df8356 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 13 Jul 2026 09:27:12 +0200 Subject: [PATCH 1/4] perf(workflow): Implement result cache for IP checks Signed-off-by: Joas Schilling --- .../lib/Check/RequestRemoteAddress.php | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/apps/workflowengine/lib/Check/RequestRemoteAddress.php b/apps/workflowengine/lib/Check/RequestRemoteAddress.php index c3f50f9967aa0..aee1a626087d7 100644 --- a/apps/workflowengine/lib/Check/RequestRemoteAddress.php +++ b/apps/workflowengine/lib/Check/RequestRemoteAddress.php @@ -11,6 +11,8 @@ use OCP\WorkflowEngine\ICheck; class RequestRemoteAddress implements ICheck { + /** @var array */ + protected array $checked = []; /** * @param IL10N $l @@ -29,18 +31,24 @@ public function __construct( */ #[\Override] public function executeCheck($operator, $value) { + $cacheKey = sha1($operator . $value); + + if (isset($this->checked[$cacheKey])) { + return $this->checked[$cacheKey]; + } + $actualValue = $this->request->getRemoteAddress(); $decodedValue = explode('/', $value); - if ($operator === 'matchesIPv4') { - return $this->matchIPv4($actualValue, $decodedValue[0], (int)$decodedValue[1]); - } elseif ($operator === '!matchesIPv4') { - return !$this->matchIPv4($actualValue, $decodedValue[0], (int)$decodedValue[1]); - } elseif ($operator === 'matchesIPv6') { - return $this->matchIPv6($actualValue, $decodedValue[0], (int)$decodedValue[1]); - } else { - return !$this->matchIPv6($actualValue, $decodedValue[0], (int)$decodedValue[1]); - } + $result = match ($operator) { + 'matchesIPv4' => $this->matchIPv4($actualValue, $decodedValue[0], (int)$decodedValue[1]), + '!matchesIPv4' => !$this->matchIPv4($actualValue, $decodedValue[0], (int)$decodedValue[1]), + 'matchesIPv6' => $this->matchIPv6($actualValue, $decodedValue[0], (int)$decodedValue[1]), + default => !$this->matchIPv6($actualValue, $decodedValue[0], (int)$decodedValue[1]), + }; + + $this->checked[$cacheKey] = $result; + return $result; } /** From 4a6088a0485de25effe391e3b47a159ce6aec3bb Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 13 Jul 2026 09:27:47 +0200 Subject: [PATCH 2/4] perf(workflows): Fix cache in request time check Signed-off-by: Joas Schilling --- apps/workflowengine/lib/Check/RequestTime.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/workflowengine/lib/Check/RequestTime.php b/apps/workflowengine/lib/Check/RequestTime.php index 87b99c841d4cf..9af37960007c8 100644 --- a/apps/workflowengine/lib/Check/RequestTime.php +++ b/apps/workflowengine/lib/Check/RequestTime.php @@ -33,7 +33,7 @@ public function __construct( */ #[\Override] public function executeCheck($operator, $value) { - $valueHash = md5($value); + $valueHash = sha1($operator . $value); if (isset($this->cachedResults[$valueHash])) { return $this->cachedResults[$valueHash]; @@ -51,7 +51,10 @@ public function executeCheck($operator, $value) { $in = $timestamp1 <= $timestamp || $timestamp <= $timestamp2; } - return ($operator === 'in') ? $in : !$in; + $result = ($operator === 'in') ? $in : !$in; + + $this->cachedResults[$valueHash] = $result; + return $result; } /** From 25b49a28223e3e540863bfbb2945d8a48d33f659 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 13 Jul 2026 09:28:30 +0200 Subject: [PATCH 3/4] chore(workflow): Simplify code in URL check Signed-off-by: Joas Schilling --- apps/workflowengine/lib/Check/RequestURL.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/workflowengine/lib/Check/RequestURL.php b/apps/workflowengine/lib/Check/RequestURL.php index 9f64517dff47b..da438e686d230 100644 --- a/apps/workflowengine/lib/Check/RequestURL.php +++ b/apps/workflowengine/lib/Check/RequestURL.php @@ -72,7 +72,7 @@ protected function isWebDAVRequest(): bool { if ($this->url === RequestURL::CLI) { return false; } - return substr($this->request->getScriptName(), 0 - strlen('/remote.php')) === '/remote.php' && ( + return str_ends_with($this->request->getScriptName(), '/remote.php') && ( $this->request->getPathInfo() === '/webdav' || str_starts_with($this->request->getPathInfo() ?? '', '/webdav/') || $this->request->getPathInfo() === '/dav/files' From 3b8be8384b2d62bad0da156b74f0a68fd6df3212 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 13 Jul 2026 11:06:15 +0200 Subject: [PATCH 4/4] chore(workflows): Migrate to CappedMemoryCache Signed-off-by: Joas Schilling --- apps/workflowengine/lib/Check/RequestRemoteAddress.php | 5 +++-- apps/workflowengine/lib/Check/RequestTime.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/workflowengine/lib/Check/RequestRemoteAddress.php b/apps/workflowengine/lib/Check/RequestRemoteAddress.php index aee1a626087d7..281f4a63b0ec0 100644 --- a/apps/workflowengine/lib/Check/RequestRemoteAddress.php +++ b/apps/workflowengine/lib/Check/RequestRemoteAddress.php @@ -6,13 +6,13 @@ */ namespace OCA\WorkflowEngine\Check; +use OCP\Cache\CappedMemoryCache; use OCP\IL10N; use OCP\IRequest; use OCP\WorkflowEngine\ICheck; class RequestRemoteAddress implements ICheck { - /** @var array */ - protected array $checked = []; + protected CappedMemoryCache $checked; /** * @param IL10N $l @@ -22,6 +22,7 @@ public function __construct( protected IL10N $l, protected IRequest $request, ) { + $this->checked = new CappedMemoryCache(); } /** diff --git a/apps/workflowengine/lib/Check/RequestTime.php b/apps/workflowengine/lib/Check/RequestTime.php index 9af37960007c8..3c69e8d88d85a 100644 --- a/apps/workflowengine/lib/Check/RequestTime.php +++ b/apps/workflowengine/lib/Check/RequestTime.php @@ -7,6 +7,7 @@ namespace OCA\WorkflowEngine\Check; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Cache\CappedMemoryCache; use OCP\IL10N; use OCP\WorkflowEngine\ICheck; @@ -14,8 +15,7 @@ class RequestTime implements ICheck { public const REGEX_TIME = '([0-1][0-9]|2[0-3]):([0-5][0-9])'; public const REGEX_TIMEZONE = '([a-zA-Z]+(?:\\/[a-zA-Z\-\_]+)+)'; - /** @var bool[] */ - protected $cachedResults; + protected CappedMemoryCache $cachedResults; /** * @param ITimeFactory $timeFactory @@ -24,6 +24,7 @@ public function __construct( protected IL10N $l, protected ITimeFactory $timeFactory, ) { + $this->cachedResults = new CappedMemoryCache(); } /**