From c7847464b1610116deeda7d371b6105a35500d23 Mon Sep 17 00:00:00 2001
From: Thibault Dockx <thibault.dockx@fusiondirectory.org>
Date: Mon, 7 Apr 2025 17:10:31 +0100
Subject: [PATCH 1/5] :art: feat(audit) - enhance Audit class to support syslog
 audits and improve array filtering

---
 plugins/tasks/Audit.php | 57 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 6 deletions(-)

diff --git a/plugins/tasks/Audit.php b/plugins/tasks/Audit.php
index 9481831..ed529f3 100644
--- a/plugins/tasks/Audit.php
+++ b/plugins/tasks/Audit.php
@@ -2,14 +2,11 @@
 
 class Audit implements EndpointInterface
 {
-
   private TaskGateway $gateway;
-  private Utils $utils;
 
   public function __construct (TaskGateway $gateway)
   {
     $this->gateway = $gateway;
-    $this->utils = new Utils();
   }
 
   /**
@@ -46,15 +43,28 @@ class Audit implements EndpointInterface
    */
   public function processEndPointPatch (array $data = NULL): array
   {
-    $result = $this->processAuditDeletion($this->gateway->getObjectTypeTask('Audit'));
+    // Check if audit type is specified in data
+    $auditType = $data['type'] ?? 'standard'; // Default to standard audit
+    
+    if ($auditType === 'syslog') {
+      // Process syslog audit
+      $result = $this->processSyslogAuditTransformation($this->gateway->getObjectTypeTask('Audit-Syslog'));
+    } else {
+      // Process standard audit
+      $result = $this->processAuditDeletion($this->gateway->getObjectTypeTask('Audit'));
+    }
 
     // Recursive function to filter out empty arrays at any depth
-    $nonEmptyResults = $this->utils->recursiveArrayFilter($result);
+    $nonEmptyResults = $this->recursiveArrayFilter($result);
 
     if (!empty($nonEmptyResults)) {
       return $nonEmptyResults;
     } else {
-      return ['No audit requiring removal'];
+      if ($auditType === 'syslog') {
+        return ['No syslog audit entries requiring removal'];
+      } else {
+        return ['No standard audit entries requiring removal'];
+      }
     }
   }
 
@@ -85,6 +95,26 @@ class Audit implements EndpointInterface
     return $result;
   }
 
+  /**
+   * @param array $syslogAuditSubTasks
+   * @return array
+   * @throws Exception
+   */
+  public function processSyslogAuditTransformation (array $syslogAuditSubTasks): array
+  {
+    $result = [];
+
+    print_r($syslogAuditSubTasks);
+    exit;
+    
+    foreach ($syslogAuditSubTasks as $task) {
+      // Similar to processAuditDeletion but for syslog
+      // ...
+    }
+    
+    return $result;
+  }
+
   /**
    * @param string $mainTaskDn
    * @return array
@@ -121,4 +151,19 @@ class Audit implements EndpointInterface
 
     return $audit;
   }
+
+   /**
+   * @param array $array
+   * @return array
+   * Note : Recursively filters out empty values and arrays at any depth.
+   */
+  public function recursiveArrayFilter (array $array): array
+  {
+    return array_filter($array, function ($item) {
+      if (is_array($item)) {
+          $item = $this->recursiveArrayFilter($item);
+      }
+      return !empty($item);
+    });
+  }
 }
\ No newline at end of file
-- 
GitLab


From 1e027117cd865440c0f5e87deb9729c275e37d4a Mon Sep 17 00:00:00 2001
From: Thibault Dockx <thibault.dockx@fusiondirectory.org>
Date: Mon, 7 Apr 2025 17:56:04 +0100
Subject: [PATCH 2/5] :art: feat(audit) - implement syslog transformation for
 audit entries and handle duplicate entries

---
 plugins/tasks/Audit.php | 171 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 164 insertions(+), 7 deletions(-)

diff --git a/plugins/tasks/Audit.php b/plugins/tasks/Audit.php
index ed529f3..85990a0 100644
--- a/plugins/tasks/Audit.php
+++ b/plugins/tasks/Audit.php
@@ -61,7 +61,7 @@ class Audit implements EndpointInterface
       return $nonEmptyResults;
     } else {
       if ($auditType === 'syslog') {
-        return ['No syslog audit entries requiring removal'];
+        return ['No audit entries requiring transformation'];
       } else {
         return ['No standard audit entries requiring removal'];
       }
@@ -104,12 +104,153 @@ class Audit implements EndpointInterface
   {
     $result = [];
 
-    print_r($syslogAuditSubTasks);
-    exit;
-    
     foreach ($syslogAuditSubTasks as $task) {
-      // Similar to processAuditDeletion but for syslog
-      // ...
+      try {
+        // If the task must be treated - status and scheduled - process the sub-tasks
+        if ($this->gateway->statusAndScheduleCheck($task)) {
+          // Retrieve data from the main task
+          $auditMainTask = $this->getAuditMainTask($task['fdtasksgranularmaster'][0]);
+          
+          // Get all audit entries with all attributes
+          $auditEntries = $this->gateway->getLdapTasks('(objectClass=fdAuditEvent)', ['*'], '', '');
+          $this->gateway->unsetCountKeys($auditEntries);
+          
+          if (empty($auditEntries)) {
+            $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
+            $result[] = ["dn" => $task['dn'], "message" => "No audit entries found to transform"];
+            continue;
+          }
+          
+          // Create syslog file
+          $path = '/var/log/fusiondirectory/';
+          $this->ensureDirectoryExists($path);
+          
+          $date = date('Y-m-d');
+          $filename = $path . 'fd-audit-' . $date . '.log';
+          
+          // Track which audit IDs are already in the file to prevent duplicates
+          $existingAuditIds = [];
+          
+          // Read existing file if it exists to extract audit IDs
+          if (file_exists($filename)) {
+            $existingContent = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+            foreach ($existingContent as $line) {
+              // Extract audit ID from the line using regex
+              if (preg_match('/id="([^"]+)"/', $line, $matches)) {
+                $existingAuditIds[] = $matches[1];
+              }
+            }
+          }
+          
+          // Open file for writing (append mode)
+          $handle = fopen($filename, 'a');
+          if ($handle === false) {
+            throw new Exception("Could not open file: $filename");
+          }
+          
+          $count = 0;
+          $skipped = 0;
+          
+          foreach ($auditEntries as $entry) {
+            // Skip entry if its ID is already in the file
+            $auditId = $entry['fdauditid'][0] ?? 'unknown';
+            if (in_array($auditId, $existingAuditIds)) {
+              $skipped++;
+              continue;
+            }
+            
+            // Parse LDAP timestamp format (YYYYMMDDHHmmss.SSSSSSZ)
+            $timestamp = '';
+            if (isset($entry['fdauditdatetime'][0])) {
+              // Extract date parts from LDAP format
+              $dateStr = $entry['fdauditdatetime'][0];
+              if (preg_match('/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $dateStr, $matches)) {
+                $year = $matches[1];
+                $month = $matches[2];
+                $day = $matches[3];
+                $hour = $matches[4];
+                $min = $matches[5];
+                $sec = $matches[6];
+                
+                // Create a datetime object and format for syslog
+                $dt = new DateTime("$year-$month-$day $hour:$min:$sec");
+                $timestamp = $dt->format('M d H:i:s');
+              } else {
+                $timestamp = date('M d H:i:s');
+              }
+            } else {
+              $timestamp = date('M d H:i:s');
+            }
+            
+            // Get hostname (use IP if available, otherwise use system hostname)
+            $hostname = isset($entry['fdauditauthorip'][0]) ? 
+                       $entry['fdauditauthorip'][0] : gethostname();
+            
+            // Get user information (use DN if available)
+            $user = isset($entry['fdauditauthordn'][0]) ? 
+                   $entry['fdauditauthordn'][0] : 'unknown';
+            
+            // Get action
+            $action = isset($entry['fdauditaction'][0]) ? 
+                     $entry['fdauditaction'][0] : 'unknown';
+            
+            // Get object type and object
+            $objectType = isset($entry['fdauditobjecttype'][0]) ? 
+                         $entry['fdauditobjecttype'][0] : '';
+            
+            $object = isset($entry['fdauditobject'][0]) ? 
+                     $entry['fdauditobject'][0] : '';
+            
+            // Get result
+            $auditResult = isset($entry['fdauditresult'][0]) ? 
+                         $entry['fdauditresult'][0] : '';
+            
+            // Format the syslog message
+            // <priority>timestamp hostname tag: message
+            $syslogMessage = "<local4.info>$timestamp $hostname FusionDirectory-Audit: ";
+            $syslogMessage .= "id=\"" . $auditId . "\" ";
+            $syslogMessage .= "user=\"$user\" ";
+            $syslogMessage .= "action=\"$action\" ";
+            
+            if (!empty($objectType)) {
+              $syslogMessage .= "objectType=\"$objectType\" ";
+            }
+            
+            if (!empty($object)) {
+              $syslogMessage .= "object=\"$object\" ";
+            }
+            
+            if (!empty($auditResult)) {
+              $syslogMessage .= "result=\"$auditResult\" ";
+            }
+            
+            // Add attributes if available (contains changes made)
+            if (isset($entry['fdauditattributes'][0])) {
+              $syslogMessage .= "changes=\"" . $entry['fdauditattributes'][0] . "\" ";
+            }
+            
+            // Write the message to the file
+            fwrite($handle, $syslogMessage . PHP_EOL);
+            $count++;
+          }
+          
+          fclose($handle);
+          
+          // Update task status
+          $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
+          
+          // Include information about skipped entries in the result message
+          $resultMsg = "Successfully transformed $count audit entries to syslog format in $filename";
+          if ($skipped > 0) {
+            $resultMsg .= " (skipped $skipped duplicate entries)";
+          }
+          
+          $result[] = ["dn" => $task['dn'], "message" => $resultMsg];
+        }
+      } catch (Exception $e) {
+        $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage());
+        $result[] = ["dn" => $task['dn'], "message" => "Error transforming audit entries: " . $e->getMessage()];
+      }
     }
     
     return $result;
@@ -141,7 +282,7 @@ class Audit implements EndpointInterface
   /**
    * @return array
    * NOTE : simply return the list of audit entries existing in LDAP
-   */
+    */
   public function returnLdapAuditEntries () : array
   {
     // Search in LDAP for audit entries (All entries ! This can be pretty heavy.
@@ -166,4 +307,20 @@ class Audit implements EndpointInterface
       return !empty($item);
     });
   }
+
+  /**
+   * @param string $path
+   * @return bool
+   * @throws Exception
+   * Note: Create directory if it doesn't exist.
+   */
+  private function ensureDirectoryExists (string $path): bool
+  {
+    if (!is_dir($path)) {
+      if (!mkdir($path, 0755, true)) {
+        throw new Exception("Failed to create directory: $path");
+      }
+    }
+    return true;
+  }
 }
\ No newline at end of file
-- 
GitLab


From cff8bd81e84a27e62aac597b731d07c5975f97a4 Mon Sep 17 00:00:00 2001
From: Thibault Dockx <thibault.dockx@fusiondirectory.org>
Date: Tue, 8 Apr 2025 10:05:12 +0100
Subject: [PATCH 3/5] :art: feat(audit) - enhance syslog audit processing by
 implementing state tracking for last processed entries and ensuring directory
 existence

---
 plugins/tasks/Audit.php | 48 +++++++++++++++++++++++++++++++++++------
 1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/plugins/tasks/Audit.php b/plugins/tasks/Audit.php
index 85990a0..4e5cb52 100644
--- a/plugins/tasks/Audit.php
+++ b/plugins/tasks/Audit.php
@@ -103,6 +103,9 @@ class Audit implements EndpointInterface
   public function processSyslogAuditTransformation (array $syslogAuditSubTasks): array
   {
     $result = [];
+    // Define path at the beginning of the method
+    $path = '/var/log/fusiondirectory/';
+    $this->ensureDirectoryExists($path);
 
     foreach ($syslogAuditSubTasks as $task) {
       try {
@@ -111,8 +114,26 @@ class Audit implements EndpointInterface
           // Retrieve data from the main task
           $auditMainTask = $this->getAuditMainTask($task['fdtasksgranularmaster'][0]);
           
-          // Get all audit entries with all attributes
-          $auditEntries = $this->gateway->getLdapTasks('(objectClass=fdAuditEvent)', ['*'], '', '');
+          // Get the most recent audit timestamp that was already processed
+          $lastProcessedTime = null;
+
+          // Check if we have a state file recording last processed time
+          $stateFile = $path . 'fd-audit-last-processed.txt';
+          if (file_exists($stateFile)) {
+              $fileContent = trim(file_get_contents($stateFile));
+              if (!empty($fileContent)) {
+                  $lastProcessedTime = $fileContent;
+              }
+          }
+
+          // Only process entries newer than last processed
+          $filter = '(objectClass=fdAuditEvent)';
+          if ($lastProcessedTime !== null) {
+              $filter = "(&(objectClass=fdAuditEvent)(fdauditdatetime>=$lastProcessedTime))";
+          }
+
+          // Get only new audit entries
+          $auditEntries = $this->gateway->getLdapTasks($filter, ['*'], '', '');
           $this->gateway->unsetCountKeys($auditEntries);
           
           if (empty($auditEntries)) {
@@ -121,10 +142,7 @@ class Audit implements EndpointInterface
             continue;
           }
           
-          // Create syslog file
-          $path = '/var/log/fusiondirectory/';
-          $this->ensureDirectoryExists($path);
-          
+          // Create syslog file (path already defined at the beginning)
           $date = date('Y-m-d');
           $filename = $path . 'fd-audit-' . $date . '.log';
           
@@ -236,6 +254,24 @@ class Audit implements EndpointInterface
           
           fclose($handle);
           
+          // After processing all entries, save the latest timestamp
+          if (!empty($auditEntries)) {
+              // Find the most recent timestamp
+              $latestTime = null;
+              foreach ($auditEntries as $entry) {
+                  if (isset($entry['fdauditdatetime'][0])) {
+                      if ($latestTime === null || $entry['fdauditdatetime'][0] > $latestTime) {
+                          $latestTime = $entry['fdauditdatetime'][0];
+                      }
+                  }
+              }
+              
+              // Save it to the state file
+              if ($latestTime !== null) {
+                  file_put_contents($stateFile, $latestTime);
+              }
+          }
+          
           // Update task status
           $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
           
-- 
GitLab


From e900b7fa0c6d07fb2ec105508201da72ba0d9250 Mon Sep 17 00:00:00 2001
From: Thibault Dockx <thibault.dockx@fusiondirectory.org>
Date: Tue, 8 Apr 2025 10:08:39 +0100
Subject: [PATCH 4/5] :art: refactor(audit) - improve code readability by
 standardizing null checks and formatting adjustments

---
 plugins/tasks/Audit.php | 126 ++++++++++++++++++++--------------------
 1 file changed, 63 insertions(+), 63 deletions(-)

diff --git a/plugins/tasks/Audit.php b/plugins/tasks/Audit.php
index 4e5cb52..4d5145d 100644
--- a/plugins/tasks/Audit.php
+++ b/plugins/tasks/Audit.php
@@ -45,7 +45,7 @@ class Audit implements EndpointInterface
   {
     // Check if audit type is specified in data
     $auditType = $data['type'] ?? 'standard'; // Default to standard audit
-    
+
     if ($auditType === 'syslog') {
       // Process syslog audit
       $result = $this->processSyslogAuditTransformation($this->gateway->getObjectTypeTask('Audit-Syslog'));
@@ -113,42 +113,42 @@ class Audit implements EndpointInterface
         if ($this->gateway->statusAndScheduleCheck($task)) {
           // Retrieve data from the main task
           $auditMainTask = $this->getAuditMainTask($task['fdtasksgranularmaster'][0]);
-          
+
           // Get the most recent audit timestamp that was already processed
-          $lastProcessedTime = null;
+          $lastProcessedTime = NULL;
 
           // Check if we have a state file recording last processed time
           $stateFile = $path . 'fd-audit-last-processed.txt';
           if (file_exists($stateFile)) {
               $fileContent = trim(file_get_contents($stateFile));
-              if (!empty($fileContent)) {
-                  $lastProcessedTime = $fileContent;
-              }
+            if (!empty($fileContent)) {
+                $lastProcessedTime = $fileContent;
+            }
           }
 
           // Only process entries newer than last processed
           $filter = '(objectClass=fdAuditEvent)';
-          if ($lastProcessedTime !== null) {
+          if ($lastProcessedTime !== NULL) {
               $filter = "(&(objectClass=fdAuditEvent)(fdauditdatetime>=$lastProcessedTime))";
           }
 
           // Get only new audit entries
           $auditEntries = $this->gateway->getLdapTasks($filter, ['*'], '', '');
           $this->gateway->unsetCountKeys($auditEntries);
-          
+
           if (empty($auditEntries)) {
             $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
             $result[] = ["dn" => $task['dn'], "message" => "No audit entries found to transform"];
             continue;
           }
-          
+
           // Create syslog file (path already defined at the beginning)
           $date = date('Y-m-d');
           $filename = $path . 'fd-audit-' . $date . '.log';
-          
+
           // Track which audit IDs are already in the file to prevent duplicates
           $existingAuditIds = [];
-          
+
           // Read existing file if it exists to extract audit IDs
           if (file_exists($filename)) {
             $existingContent = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
@@ -159,16 +159,16 @@ class Audit implements EndpointInterface
               }
             }
           }
-          
+
           // Open file for writing (append mode)
           $handle = fopen($filename, 'a');
-          if ($handle === false) {
+          if ($handle === FALSE) {
             throw new Exception("Could not open file: $filename");
           }
-          
-          $count = 0;
+
+          $count   = 0;
           $skipped = 0;
-          
+
           foreach ($auditEntries as $entry) {
             // Skip entry if its ID is already in the file
             $auditId = $entry['fdauditid'][0] ?? 'unknown';
@@ -176,20 +176,20 @@ class Audit implements EndpointInterface
               $skipped++;
               continue;
             }
-            
+
             // Parse LDAP timestamp format (YYYYMMDDHHmmss.SSSSSSZ)
             $timestamp = '';
             if (isset($entry['fdauditdatetime'][0])) {
               // Extract date parts from LDAP format
               $dateStr = $entry['fdauditdatetime'][0];
               if (preg_match('/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $dateStr, $matches)) {
-                $year = $matches[1];
-                $month = $matches[2];
-                $day = $matches[3];
-                $hour = $matches[4];
-                $min = $matches[5];
-                $sec = $matches[6];
-                
+                $year   = $matches[1];
+                $month  = $matches[2];
+                $day    = $matches[3];
+                $hour   = $matches[4];
+                $min    = $matches[5];
+                $sec    = $matches[6];
+
                 // Create a datetime object and format for syslog
                 $dt = new DateTime("$year-$month-$day $hour:$min:$sec");
                 $timestamp = $dt->format('M d H:i:s');
@@ -199,88 +199,88 @@ class Audit implements EndpointInterface
             } else {
               $timestamp = date('M d H:i:s');
             }
-            
+
             // Get hostname (use IP if available, otherwise use system hostname)
-            $hostname = isset($entry['fdauditauthorip'][0]) ? 
+            $hostname = isset($entry['fdauditauthorip'][0]) ?
                        $entry['fdauditauthorip'][0] : gethostname();
-            
+
             // Get user information (use DN if available)
-            $user = isset($entry['fdauditauthordn'][0]) ? 
+            $user = isset($entry['fdauditauthordn'][0]) ?
                    $entry['fdauditauthordn'][0] : 'unknown';
-            
+
             // Get action
-            $action = isset($entry['fdauditaction'][0]) ? 
+            $action = isset($entry['fdauditaction'][0]) ?
                      $entry['fdauditaction'][0] : 'unknown';
-            
+
             // Get object type and object
-            $objectType = isset($entry['fdauditobjecttype'][0]) ? 
+            $objectType = isset($entry['fdauditobjecttype'][0]) ?
                          $entry['fdauditobjecttype'][0] : '';
-            
-            $object = isset($entry['fdauditobject'][0]) ? 
+
+            $object = isset($entry['fdauditobject'][0]) ?
                      $entry['fdauditobject'][0] : '';
-            
+
             // Get result
-            $auditResult = isset($entry['fdauditresult'][0]) ? 
+            $auditResult = isset($entry['fdauditresult'][0]) ?
                          $entry['fdauditresult'][0] : '';
-            
+
             // Format the syslog message
             // <priority>timestamp hostname tag: message
             $syslogMessage = "<local4.info>$timestamp $hostname FusionDirectory-Audit: ";
             $syslogMessage .= "id=\"" . $auditId . "\" ";
             $syslogMessage .= "user=\"$user\" ";
             $syslogMessage .= "action=\"$action\" ";
-            
+
             if (!empty($objectType)) {
               $syslogMessage .= "objectType=\"$objectType\" ";
             }
-            
+
             if (!empty($object)) {
               $syslogMessage .= "object=\"$object\" ";
             }
-            
+
             if (!empty($auditResult)) {
               $syslogMessage .= "result=\"$auditResult\" ";
             }
-            
+
             // Add attributes if available (contains changes made)
             if (isset($entry['fdauditattributes'][0])) {
               $syslogMessage .= "changes=\"" . $entry['fdauditattributes'][0] . "\" ";
             }
-            
+
             // Write the message to the file
             fwrite($handle, $syslogMessage . PHP_EOL);
             $count++;
           }
-          
+
           fclose($handle);
-          
+
           // After processing all entries, save the latest timestamp
           if (!empty($auditEntries)) {
-              // Find the most recent timestamp
-              $latestTime = null;
-              foreach ($auditEntries as $entry) {
-                  if (isset($entry['fdauditdatetime'][0])) {
-                      if ($latestTime === null || $entry['fdauditdatetime'][0] > $latestTime) {
-                          $latestTime = $entry['fdauditdatetime'][0];
-                      }
-                  }
-              }
-              
-              // Save it to the state file
-              if ($latestTime !== null) {
-                  file_put_contents($stateFile, $latestTime);
+            // Find the most recent timestamp
+            $latestTime = NULL;
+            foreach ($auditEntries as $entry) {
+              if (isset($entry['fdauditdatetime'][0])) {
+                if ($latestTime === NULL || $entry['fdauditdatetime'][0] > $latestTime) {
+                  $latestTime = $entry['fdauditdatetime'][0];
+                }
               }
+            }
+
+            // Save it to the state file
+            if ($latestTime !== NULL) {
+              file_put_contents($stateFile, $latestTime);
+            }
           }
-          
+
           // Update task status
           $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
-          
+
           // Include information about skipped entries in the result message
           $resultMsg = "Successfully transformed $count audit entries to syslog format in $filename";
           if ($skipped > 0) {
             $resultMsg .= " (skipped $skipped duplicate entries)";
           }
-          
+
           $result[] = ["dn" => $task['dn'], "message" => $resultMsg];
         }
       } catch (Exception $e) {
@@ -288,7 +288,7 @@ class Audit implements EndpointInterface
         $result[] = ["dn" => $task['dn'], "message" => "Error transforming audit entries: " . $e->getMessage()];
       }
     }
-    
+
     return $result;
   }
 
@@ -353,10 +353,10 @@ class Audit implements EndpointInterface
   private function ensureDirectoryExists (string $path): bool
   {
     if (!is_dir($path)) {
-      if (!mkdir($path, 0755, true)) {
+      if (!mkdir($path, 0755, TRUE)) {
         throw new Exception("Failed to create directory: $path");
       }
     }
-    return true;
+    return TRUE;
   }
 }
\ No newline at end of file
-- 
GitLab


From 64cb5624e6db7be2f657532319e380ffe803cd83 Mon Sep 17 00:00:00 2001
From: Thibault Dockx <thibault.dockx@fusiondirectory.org>
Date: Tue, 8 Apr 2025 10:29:48 +0100
Subject: [PATCH 5/5] :art: refactor(audit) - clarify empty audit entries check
 by using count() for better readability

---
 plugins/tasks/Audit.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/plugins/tasks/Audit.php b/plugins/tasks/Audit.php
index 4d5145d..fbe474b 100644
--- a/plugins/tasks/Audit.php
+++ b/plugins/tasks/Audit.php
@@ -136,7 +136,8 @@ class Audit implements EndpointInterface
           $auditEntries = $this->gateway->getLdapTasks($filter, ['*'], '', '');
           $this->gateway->unsetCountKeys($auditEntries);
 
-          if (empty($auditEntries)) {
+          // Check if there are no audit entries
+          if (count($auditEntries) === 0) {
             $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
             $result[] = ["dn" => $task['dn'], "message" => "No audit entries found to transform"];
             continue;
-- 
GitLab