[pmg-devel] [PATCH WIP api 11/11] match groups: implement matching logic

Leo Nunner l.nunner at proxmox.com
Thu Sep 14 11:52:32 CEST 2023


Implements the logic behind match groups; A match group holds
several objects inside it, and only evalutes to true if ALL the
contained objects evaluate to true. Match groups are connected via
logical 'or' to all other objects inside the rule:

- Rule
    - Match Group
	- Object 1
	- Object 2
    - Object 3

This rule will match if either (Object 1 && Object 2), or if Object 3
evaluate to true.

Signed-off-by: Leo Nunner <l.nunner at proxmox.com>
---
 src/PMG/RuleCache.pm | 50 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 7 deletions(-)

diff --git a/src/PMG/RuleCache.pm b/src/PMG/RuleCache.pm
index 115bf1a..9e30460 100644
--- a/src/PMG/RuleCache.pm
+++ b/src/PMG/RuleCache.pm
@@ -253,11 +253,19 @@ sub from_match {
 	$ip = $1;
     }
 
+    # don't return true if there are no elements marked with and!
+    my $and = grep { $_->{and} } @$from;
     foreach my $obj (@$from) {
-	return 1 if ($obj->who_match($addr, $ip, $ldap) xor $obj->{negate});
+	my $match = ($obj->who_match($addr, $ip, $ldap) xor $obj->{negate});
+
+	if ($obj->{and}) {
+	    $and &&= $match;
+	} else {
+	    return 1 if $match;
+	}
     }
 
-    return 0;
+    return $and;
 }
 
 sub to_match {
@@ -267,11 +275,18 @@ sub to_match {
 
     return 1 if !defined ($to);
 
+    my $and = grep { $_->{and} } @$to;
     foreach my $obj (@$to) {
-	return 1 if ($obj->who_match($addr, undef, $ldap) xor $obj->{negate});
+	my $match = ($obj->who_match($addr, undef, $ldap) xor $obj->{negate});
+
+	if ($obj->{and}) {
+	    $and &&= $match;
+	} else {
+	    return 1 if $match;
+	}
     }
 
-    return 0;
+    return $and;
 }
 
 sub when_match {
@@ -281,11 +296,18 @@ sub when_match {
 
     return 1 if !defined ($when);
 
+    my $and = grep { $_->{and} } @$when;
     foreach my $obj (@$when) {
-	return 1 if ($obj->when_match($time) xor $obj->{negate});
+	my $match = ($obj->when_match($time) xor $obj->{negate});
+
+	if ($obj->{and}) {
+	    $and &&= $match;
+	} else {
+	    return 1 if $match;
+	}
     }
 
-    return 0;
+    return $and;
 }
 
 sub what_match {
@@ -311,14 +333,28 @@ sub what_match {
 
     my $marks;
 
+    # First, we loop through all objects which are not 'Spam Filter'
+    my $group_valid = 1;
+    my @group_matches = ();
     foreach my $obj (@$what) {
 	if (!$obj->can('what_match_targets')) {
 	    if (my $match = $obj->what_match($queue, $element, $msginfo, $dbh)) {
-		push @$marks, @$match;
+		if ($obj->{and}) {
+		    push @group_matches, $match;
+		} else {
+		    push @$marks, @$match;
+		}
+	    } elsif ($obj->{and}) {
+		$group_valid = 0;
 	    }
 	}
     }
 
+    # If the 'Match All' group matches, push everything into the list
+    if ($group_valid) {
+	push(@$marks, @group_matches);
+    }
+
     foreach my $target (@{$msginfo->{targets}}) {
 	$res->{$target}->{marks} = $marks;
 	$res->{marks} = $marks;
-- 
2.39.2





More information about the pmg-devel mailing list