changeset 708:43245004c8e2 sql-opti

refactored audit logs: use AuditLogHandler
author Alain Mazy <am@orthanc.team>
date Tue, 15 Jul 2025 14:24:14 +0200
parents 86e27eadc5cc
children a88a2776fea4
files Framework/Common/BinaryStringValue.cpp Framework/Common/BinaryStringValue.h Framework/Common/Dictionary.cpp Framework/Common/Dictionary.h Framework/Plugins/DatabaseBackendAdapterV4.cpp Framework/Plugins/IDatabaseBackend.h Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexBackend.h PostgreSQL/NEWS
diffstat 9 files changed, 65 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Common/BinaryStringValue.cpp	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Common/BinaryStringValue.cpp	Tue Jul 15 14:24:14 2025 +0200
@@ -32,7 +32,8 @@
 namespace OrthancDatabases
 {
   BinaryStringValue::BinaryStringValue(const void* data,
-                                       size_t size)
+                                       size_t size) :
+    isNull_(false)
   {
     if (data == NULL && size > 0)
     {
--- a/Framework/Common/BinaryStringValue.h	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Common/BinaryStringValue.h	Tue Jul 15 14:24:14 2025 +0200
@@ -33,14 +33,17 @@
   {
   private:
     std::string  content_;
+    bool isNull_;
 
   public:
-    BinaryStringValue()
+    BinaryStringValue() :
+      isNull_(true)
     {
     }
 
     explicit BinaryStringValue(const std::string& content) :
-      content_(content)
+      content_(content),
+      isNull_(false)
     {
     }
 
@@ -73,5 +76,10 @@
     }
     
     virtual IValue* Convert(ValueType target) const ORTHANC_OVERRIDE;
+
+    virtual bool IsNull() const ORTHANC_OVERRIDE
+    {
+      return isNull_;
+    }
   };
 }
--- a/Framework/Common/Dictionary.cpp	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Common/Dictionary.cpp	Tue Jul 15 14:24:14 2025 +0200
@@ -147,6 +147,10 @@
     SetValue(key, new Utf8StringValue());
   }
 
+  void Dictionary::SetBinaryNullValue(const std::string& key)
+  {
+    SetValue(key, new BinaryStringValue());
+  }
   
   const IValue& Dictionary::GetValue(const std::string& key) const
   {
--- a/Framework/Common/Dictionary.h	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Common/Dictionary.h	Tue Jul 15 14:24:14 2025 +0200
@@ -67,6 +67,8 @@
                         const void* data,
                         size_t size);
 
+    void SetBinaryNullValue(const std::string& key);
+
     void SetFileValue(const std::string& key,
                       const std::string& file);
 
--- a/Framework/Plugins/DatabaseBackendAdapterV4.cpp	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV4.cpp	Tue Jul 15 14:24:14 2025 +0200
@@ -47,7 +47,7 @@
 namespace OrthancDatabases
 {
   static bool isBackendInUse_ = false;  // Only for sanity checks
-
+  static BaseIndexConnectionsPool* connectionPool_ = NULL;  // Only for the AuditLogHandler
 
   static Orthanc::DatabasePluginMessages::ResourceType Convert(OrthancPluginResourceType resourceType)
   {
@@ -467,10 +467,6 @@
         response.mutable_get_system_information()->set_supports_key_value_stores(accessor.GetBackend().HasKeyValueStores());
 #endif
 
-#if ORTHANC_PLUGINS_HAS_AUDIT_LOGS == 1
-        response.mutable_get_system_information()->set_supports_audit_logs(accessor.GetBackend().HasAuditLogs());
-#endif
-
         break;
       }
 
@@ -1410,17 +1406,6 @@
         break;
 #endif
 
-#if ORTHANC_PLUGINS_HAS_AUDIT_LOGS == 1
-      case Orthanc::DatabasePluginMessages::OPERATION_RECORD_AUDIT_LOG:
-        backend.RecordAuditLog(manager,
-                               request.record_audit_log().user_id(),
-                               Convert(request.record_audit_log().resource_type()),
-                               request.record_audit_log().resource_id(),
-                               request.record_audit_log().action(),
-                               request.record_audit_log().log_data());
-        break;
-
-#endif
       default:
         LOG(ERROR) << "Not implemented transaction operation from protobuf: " << request.operation();
         throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
@@ -1523,6 +1508,7 @@
       if (isBackendInUse_)
       {
         isBackendInUse_ = false;
+        connectionPool_ = NULL;
       }
       else
       {
@@ -1537,6 +1523,29 @@
     }
   }
 
+
+  OrthancPluginErrorCode AuditLogHandler(const char*               userId,
+                                         OrthancPluginResourceType resourceType,
+                                         const char*               resourceId,
+                                         const char*               action,
+                                         const void*               logData,
+                                         uint32_t                  logDataSize)
+  {
+    if (!isBackendInUse_ || connectionPool_ == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+
+    BaseIndexConnectionsPool::Accessor accessor(*connectionPool_);
+    accessor.GetBackend().RecordAuditLog(accessor.GetManager(),
+                                         userId,
+                                         resourceType,
+                                         resourceId,
+                                         action,
+                                         logData,
+                                         logDataSize);
+    return OrthancPluginErrorCode_Success;                                     
+  }
   
   void DatabaseBackendAdapterV4::Register(IndexBackend* backend,
                                           size_t countConnections,
@@ -1561,6 +1570,7 @@
     }
 
     OrthancPluginContext* context = backend->GetContext();
+    connectionPool_ = pool.get(); // we need to keep a pointer on the connectionPool for the static Audit log handler
  
     if (OrthancPluginRegisterDatabaseBackendV4(context, pool.release(), maxDatabaseRetries,
                                                CallBackend, FinalizeBackend) != OrthancPluginErrorCode_Success)
@@ -1570,6 +1580,10 @@
     }
 
     isBackendInUse_ = true;
+
+#if ORTHANC_PLUGINS_HAS_AUDIT_LOGS == 1
+    OrthancPluginRegisterAuditLogHandler(context, AuditLogHandler);
+#endif
   }
 
 
--- a/Framework/Plugins/IDatabaseBackend.h	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Plugins/IDatabaseBackend.h	Tue Jul 15 14:24:14 2025 +0200
@@ -467,7 +467,8 @@
                                 OrthancPluginResourceType type,
                                 const std::string& resourceId,
                                 const std::string& action,
-                                const std::string& value) = 0;
+                                const void* logData,
+                                uint32_t logDataSize) = 0;
 #endif
 
     virtual bool HasPerformDbHousekeeping() = 0;
--- a/Framework/Plugins/IndexBackend.cpp	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Plugins/IndexBackend.cpp	Tue Jul 15 14:24:14 2025 +0200
@@ -4689,7 +4689,8 @@
                                       OrthancPluginResourceType resourceType,
                                       const std::string& resourceId,
                                       const std::string& action,
-                                      const std::string& value)
+                                      const void* logData,
+                                      uint32_t logDataSize)
     {
       DatabaseManager::CachedStatement statement(
         STATEMENT_FROM_HERE, manager,
@@ -4709,7 +4710,15 @@
       args.SetUtf8Value("resourceId", resourceId);
       args.SetUtf8Value("action", action);
       args.SetUtf8Value("userId", userId);
-      args.SetBinaryValue("logData", value);
+      
+      if (logData != NULL && logDataSize > 0)
+      {
+        args.SetBinaryValue("logData", logData, logDataSize);
+      }
+      else
+      {
+        args.SetBinaryNullValue("logData");
+      }
 
       statement.Execute(args);
     }
--- a/Framework/Plugins/IndexBackend.h	Tue Jul 15 10:19:23 2025 +0200
+++ b/Framework/Plugins/IndexBackend.h	Tue Jul 15 14:24:14 2025 +0200
@@ -527,7 +527,8 @@
                                 OrthancPluginResourceType type,
                                 const std::string& resourceId,
                                 const std::string& action,
-                                const std::string& value) ORTHANC_OVERRIDE;
+                                const void* logData,
+                                uint32_t logDataSize) ORTHANC_OVERRIDE;
 #endif
 
 
--- a/PostgreSQL/NEWS	Tue Jul 15 10:19:23 2025 +0200
+++ b/PostgreSQL/NEWS	Tue Jul 15 14:24:14 2025 +0200
@@ -20,7 +20,8 @@
   of being idle or one hour after their creation.
 * New metrics "orthanc_index_active_connections_count" showing the current number
   of active connections.
-* Added support for AuditLogs.
+* Added support for AuditLogs.  The PostgreSQL plugin is listening to audit logs
+  and is storing them in the SQL Database.
 
 Maintenance:
 * Optimized the CreateInstance SQL query.