From fb21bb970d131da73622b24df043293b7c0cd60b Mon Sep 17 00:00:00 2001
From: Johan de Klerk <jdeklerk00@gmail.com>
Date: Wed, 13 Apr 2022 14:28:34 +0200
Subject: [PATCH] Deeper object changes for audit events

---
 audit/audit.go | 53 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/audit/audit.go b/audit/audit.go
index 1907683..6dff2b1 100644
--- a/audit/audit.go
+++ b/audit/audit.go
@@ -38,27 +38,7 @@ func GetChanges(original interface{}, new interface{}) (map[string]interface{},
 			// 0 = Object
 			// 1 = field
 
-			objectKey := ToSnakeCase(change.Path[0])
-			field := ToSnakeCase(change.Path[1])
-
-			existingObject, present := changes[objectKey]
-			if present {
-				if object, ok := existingObject.(map[string]interface{}); ok {
-					object[field] = FieldChange{
-						From: change.From,
-						To:   change.To,
-					}
-					changes[objectKey] = object
-				}
-			} else {
-				fieldChange := map[string]interface{}{
-					field: FieldChange{
-						From: change.From,
-						To:   change.To,
-					},
-				}
-				changes[objectKey] = fieldChange
-			}
+			ChildObjectChanges(changes, change.Path[0], change.Path[1], change.From, change.To)
 
 		} else if len(change.Path) == 3 {
 			// Array of objects
@@ -69,6 +49,13 @@ func GetChanges(original interface{}, new interface{}) (map[string]interface{},
 
 			objectKey := ToSnakeCase(change.Path[0])
 			indexString := change.Path[1]
+
+			if !string_utils.IsNumericString(indexString) {
+				// Not an array, but an deeper nested object
+				ChildObjectChanges(changes, change.Path[len(change.Path)-2], change.Path[len(change.Path)-1], change.From, change.To)
+				continue
+			}
+
 			index, _ := string_utils.StringToInt64(indexString)
 			field := ToSnakeCase(change.Path[2])
 
@@ -111,6 +98,30 @@ func GetChanges(original interface{}, new interface{}) (map[string]interface{},
 
 	return changes, nil
 }
+func ChildObjectChanges(changes map[string]interface{}, objectPath string, fieldPath string, changeFrom interface{}, changeTo interface{}) {
+
+	objectKey := ToSnakeCase(objectPath)
+	field := ToSnakeCase(fieldPath)
+
+	existingObject, present := changes[objectKey]
+	if present {
+		if object, ok := existingObject.(map[string]interface{}); ok {
+			object[field] = FieldChange{
+				From: changeFrom,
+				To:   changeTo,
+			}
+			changes[objectKey] = object
+		}
+	} else {
+		fieldChange := map[string]interface{}{
+			field: FieldChange{
+				From: changeFrom,
+				To:   changeTo,
+			},
+		}
+		changes[objectKey] = fieldChange
+	}
+}
 
 // GetAllChanges Returns the diff, structured in json, recursively
 // Be warned, here be dragons. Debug this first to understand how it works
-- 
GitLab