From 28c0eea8cb0e1016e751a2e28d0b09006751c58b Mon Sep 17 00:00:00 2001
From: Arthur Schiwon <blizzz@arthur-schiwon.de>
Date: Fri, 21 Aug 2020 17:36:01 +0200
Subject: [PATCH] fix possible leaking scope in Flow

- a configured flow can be brought into consideration, despite its event
  was not fired
- it could either run through
- or run into a RuntimeException and killing processing of valid flows

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
---
 apps/workflowengine/lib/AppInfo/Application.php |  2 ++
 apps/workflowengine/lib/Service/RuleMatcher.php | 14 ++++++++++++++
 lib/public/WorkflowEngine/IRuleMatcher.php      | 10 ++++++++++
 3 files changed, 26 insertions(+)

diff --git a/apps/workflowengine/lib/AppInfo/Application.php b/apps/workflowengine/lib/AppInfo/Application.php
index 8f762f0d707..3b253acbce1 100644
--- a/apps/workflowengine/lib/AppInfo/Application.php
+++ b/apps/workflowengine/lib/AppInfo/Application.php
@@ -65,6 +65,7 @@ class Application extends App implements IBootstrap {
 	private function registerRuleListeners(IEventDispatcher $dispatcher,
 										   IServerContainer $container,
 										   ILogger $logger): void {
+		/** @var Manager $manager */
 		$manager = $container->query(Manager::class);
 		$configuredEvents = $manager->getAllConfiguredEvents();
 
@@ -81,6 +82,7 @@ class Application extends App implements IBootstrap {
 								/** @var IOperation $operation */
 								$operation = $container->query($operationClass);
 
+								$ruleMatcher->setEventName($eventName);
 								$ruleMatcher->setEntity($entity);
 								$ruleMatcher->setOperation($operation);
 
diff --git a/apps/workflowengine/lib/Service/RuleMatcher.php b/apps/workflowengine/lib/Service/RuleMatcher.php
index 05ea16d6816..0ae26627427 100644
--- a/apps/workflowengine/lib/Service/RuleMatcher.php
+++ b/apps/workflowengine/lib/Service/RuleMatcher.php
@@ -62,6 +62,8 @@ class RuleMatcher implements IRuleMatcher {
 	protected $entity;
 	/** @var Logger */
 	protected $logger;
+	/** @var string */
+	protected $eventName;
 
 	public function __construct(
 		IUserSession $session,
@@ -101,6 +103,13 @@ class RuleMatcher implements IRuleMatcher {
 		$this->entity = $entity;
 	}
 
+	public function setEventName(string $eventName): void {
+		if ($this->eventName !== null) {
+			throw new RuntimeException('This method must not be called more than once');
+		}
+		$this->eventName = $eventName;
+	}
+
 	public function getEntity(): IEntity {
 		if ($this->entity === null) {
 			throw new \LogicException('Entity was not set yet');
@@ -155,6 +164,11 @@ class RuleMatcher implements IRuleMatcher {
 
 		$matches = [];
 		foreach ($operations as $operation) {
+			$configuredEvents = json_decode($operation['events'], true);
+			if ($this->eventName !== null && !in_array($this->eventName, $configuredEvents)) {
+				continue;
+			}
+
 			$checkIds = json_decode($operation['checks'], true);
 			$checks = $this->manager->getChecks($checkIds);
 
diff --git a/lib/public/WorkflowEngine/IRuleMatcher.php b/lib/public/WorkflowEngine/IRuleMatcher.php
index cb52001a1a2..47ab3a25c3a 100644
--- a/lib/public/WorkflowEngine/IRuleMatcher.php
+++ b/lib/public/WorkflowEngine/IRuleMatcher.php
@@ -78,4 +78,14 @@ interface IRuleMatcher extends IFileCheck {
 	 * @since 18.0.0
 	 */
 	public function getEntity(): IEntity;
+
+	/**
+	 * this method can be called once to set the event name that is currently
+	 * being processed. The workflow engine takes care of this usually, only an
+	 * IComplexOperation might want to make use of it.
+	 *
+	 * @throws RuntimeException
+	 * @since 20.0.0
+	 */
+	public function setEventName(string $eventName): void;
 }
-- 
GitLab