From 21d7937a204390f31b0a91e05ac2519d163337d1 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 afb2c57febdce..b148c266976fb 100644 --- a/apps/workflowengine/lib/Check/RequestRemoteAddress.php +++ b/apps/workflowengine/lib/Check/RequestRemoteAddress.php @@ -12,6 +12,8 @@ use OCP\WorkflowEngine\ICheck; class RequestRemoteAddress implements ICheck { + /** @var array */ + protected array $checked = []; /** * @param IL10N $l @@ -30,18 +32,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 75a6822b15e7812f9ad498e03901b6f08599adbf 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 71afcf0f05701..9236c827e6ea3 100644 --- a/apps/workflowengine/lib/Check/RequestTime.php +++ b/apps/workflowengine/lib/Check/RequestTime.php @@ -34,7 +34,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]; @@ -52,7 +52,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 c0f8fa87bd773ce0be2c10eb684b0f1089735bc8 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 00b4cd22bdcac..f3e5d5ef108b1 100644 --- a/apps/workflowengine/lib/Check/RequestURL.php +++ b/apps/workflowengine/lib/Check/RequestURL.php @@ -73,7 +73,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 e7004a53878997b0357803fe07dbdff00c799739 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 b148c266976fb..7309263ebfa7c 100644 --- a/apps/workflowengine/lib/Check/RequestRemoteAddress.php +++ b/apps/workflowengine/lib/Check/RequestRemoteAddress.php @@ -7,13 +7,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 @@ -23,6 +23,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 9236c827e6ea3..5dc77ace92cd9 100644 --- a/apps/workflowengine/lib/Check/RequestTime.php +++ b/apps/workflowengine/lib/Check/RequestTime.php @@ -8,6 +8,7 @@ namespace OCA\WorkflowEngine\Check; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Cache\CappedMemoryCache; use OCP\IL10N; use OCP\WorkflowEngine\ICheck; @@ -15,8 +16,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 @@ -25,6 +25,7 @@ public function __construct( protected IL10N $l, protected ITimeFactory $timeFactory, ) { + $this->cachedResults = new CappedMemoryCache(); } /**